//+------------------------------------------------------------------+
//|                                                 Martingale_EA.mq5 |
//|                                          Copyright 2024            |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024"
#property link ""
#property version "1.00"

// 引入日志系统头文件
#include "Logger.mqh"

#include <Arrays/ArrayObj.mqh>
#include <Trade\Trade.mqh> // For CTrade class and trading functions
#include <Controls\Dialog.mqh>
#include <Controls\Label.mqh>
#include <Controls\Button.mqh>
#include <Controls\Edit.mqh>
#include "CustomDialog.mqh"  // Include our custom dialog class

// 定义日志级别常量
#define MQL_TRADE_LOG_LEVEL 0x0001
#define MQL_DEVELOPER_LOG_LEVEL 0x0002
#define LOG_LEVEL_NO 0

// ============= 基础功能参数 =============
input group "============= 基础功能参数 ============="
input bool OpenTrend = false;            // 允许顺势加仓
input int MagicNumber = 123456;          // EA识别号
input int font_size = 8;                 // 字体大小

// ============= 日志系统参数 =============
input group "============= 日志系统参数 ============="
input ENUM_LOG_LEVEL LogLevel = LOG_LEVEL_INFO;  // 日志级别
input bool EnableFileLog = true;                 // 启用文件日志
input bool EnableConsoleLog = false;             // 启用控制台日志

// ============= 加仓与手数相关参数 =============
input group "============= 加仓与手数相关参数 ============="
input double InitialLot = 0.01;          // 初始仓位
input double AtrRange = 0.8;             // 加仓atr的倍率
input double StepSize = 0;               // 手动输入的加仓步长(金额)
input int MaxOrderCount = 12;            // 最大订单数量（3.82手）
input double MultiplierOnLoss = 1.5;     // 亏损后倍数

// ============= 止盈止损相关参数 =============
input group "============= 止盈止损相关参数 ============="
input double StopProfit = 6;            // 平仓止盈金额（*订单数）
input double TakeProfitATR = 2;          // 止盈ATR倍数
input double StopLoss = -1500;           // 单方向止损
input double CloseAll = 1000;            // 总盈利达到目标平仓

// ============= 时间与挂单相关参数 =============
input group "============= 时间与挂单相关参数 ============="
input int MaxBars = 500;                 // 最大搜索K线数
input double delta = 20;                 // 止盈增益点数
input double OrderDistanceATR = 0.1;     // 挂单距离ATR倍数
input int MaxTimeLimit = 5;              // 最大持仓时间限制(分钟)
input bool sj = false;                   // 是否启用时间控制
input int star = 0;                      // 开始时间（小时）
input int end = 24;                      // 结束时间（小时）

// ============= 交易方向与锁单相关参数 =============
input group "============= 交易方向与锁单相关参数 ============="
input bool Buy = true;                   // 允许买入
input bool Sell = true;                  // 允许卖出
input bool AllowLockPosition = false;     // 允许锁单

// ============= 全局可修改参数 =============
double g_AtrRange;
double g_StopProfit;
double g_MultiplierOnLoss;
ENUM_TIMEFRAMES TF_Trailing = PERIOD_M1; // 追踪止损时间框架

double g_atr = 0; // 全局ATR值
int g_atrHandle = INVALID_HANDLE; // ATR指标句柄

// 全局变量
datetime g_startTime;      // EA启动时间
double g_InitialLot;       // 可修改的初始仓位
int g_MaxOrderCount;      // 可修改的最大订单数量
double currentLot = InitialLot;
int lastTicket = 0;
double stopLevel;
double minLot;
double maxLot;
double lotStep;
int spread;
int chartCorner;

// 添加全局变量 
double buyTotalLots = 0;
double sellTotalLots = 0;
double buyTotalValue = 0;
double sellTotalValue = 0;
double buyTotalProfit = 0;
double sellTotalProfit = 0;
double buyAveragePrice = 0;
double sellAveragePrice = 0;
double highestBuyPrice = 0;
double lowestBuyPrice = 0;
double highestSellPrice = 0;
double lowestSellPrice = 0;
int buyOrderCount = 0;
int sellOrderCount = 0;
bool isBuyLimitTriggered = false;  // 买单限制触发标志
bool isSellLimitTriggered = false; // 卖单限制触发标志

double lastBuyLot = 0; // 记录最后一单买单手数
double lastSellLot = 0; // 记录最后一单卖单手数

double buyStepPrice;
double sellStepPrice;

// 添加全局变量以记录当前的买单和卖单挂单数量
int buyPendingOrders = 0;  // 当前买单挂单数量
int sellPendingOrders = 0; // 当前卖单挂单数量

// // 添加输入变量以控制是否允许顺势加仓
// input bool AllowAddPosition = true; // 是否允许顺势加仓

// 添加新的全局变量
class CMartingaleOrderInfo : public CObject
{
public:
    ulong orderTicket;              // 订单号
    datetime orderOpenTime;         // 开单时间
    datetime orderCloseTime;        // 平仓时间
    double orderLots;               // 手数
    double orderOpenPrice;          // 开仓价
    double orderClosePrice;         // 平仓价
    double orderMaxDrawdown;        // 最大回撤
    string orderBatchId;            // 所属批次
    ENUM_ORDER_TYPE orderType;      // 订单类型
};

class CBatchInfo : public CObject
{
public:
    string batchId;               // 批次号 B/S开头
    datetime startTime;           // 开始时间
    datetime endTime;             // 结束时间
    double totalLots;             // 总手数
    double maxMultiplier;         // 最大倍率
    double maxDrawdown;           // 最大回撤
    double finalProfit;           // 最终收益
    CArrayObj orders;             // 包含的订单
    ENUM_POSITION_TYPE batchType; // 批次类型
};

CArrayObj *buyBatches;      // 买入批次记录
CArrayObj *sellBatches;     // 卖出批次记录
int buyBatchCounter = 1;    // 买单批次计数器
int sellBatchCounter = 1;   // 卖单批次计数器
bool isNewBuyBatch = true;  // 标记是否是新买入批次
bool isNewSellBatch = true; // 标记是否是新卖出批次

CTrade trade; // Declare globally if used in multiple functions

// 添加全局变量以存储买入和卖出挂单的票据
ulong buyStopTicket = 0;  // 买入挂单票据
ulong sellStopTicket = 0; // 卖出挂单票据

// 添加全局变量以记录最大回撤
double buyMaxDrawdown = 0;    // 买单最大回撤
double sellMaxDrawdown = 0;   // 卖单最大回撤
double buyCurrentProfit = 0;  // 当前买单收益
double sellCurrentProfit = 0; // 当前卖单收益

// 添加全局变量来存储订单关系
class COrderRelation : public CObject
{
public:
    ulong originalTicket;  // 原始订单号
    ulong currentTicket;   // 当前订单号
};

CArrayObj *orderRelations;  // 存储订单关系

// 添加全局变量来记录最大订单时间
datetime maxBuyTime = 0;     // 达到最大买单时的时间
datetime maxSellTime = 0;    // 达到最大卖单时的时间
double maxBuyDrawdown = 0;   // 买单最大回撤
double maxSellDrawdown = 0;  // 卖单最大回撤

// 市场状态分析相关变量
// MARKET_CONDITION g_currentMarketCondition = RANGING;
// MARKET_CONDITION g_previousMarketCondition = RANGING;
// int g_lastStateChangeBar = 0;

// 指标句柄
// int ma200Handle;
// int ma50Handle;
// int ma20Handle;
// int adxHandle;
// int rsiHandle;
// int bbHandle;

// 添加布林带相关变量
int g_bbHandle = INVALID_HANDLE;    // 布林带指标句柄
bool g_isExpanding = false;         // 布林带是否开口
int g_expansionCount = 0;           // 布林带开口计数
datetime g_lockStartTime = 0;       // 锁单开始时间

// 布林带参数
input int BB_Period = 20;           // 布林带周期
input double BB_Deviation = 2.0;    // 布林带标准差
input double BB_WidthThreshold = 0.0001; // 布林带开口阈值

// 在全局变量区域添加
int g_ma20Handle = INVALID_HANDLE;    // 20周期均线句柄
// int g_ma50Handle = INVALID_HANDLE;    // 50周期均线句柄

// 在全局变量区域添加
double g_OrderDistance = 0;             // 实际挂单距离

// 自定义马丁格尔面板类
class CMartingalePanel : public CCustomDialog
{
public:
    // 重写刷新方法
    virtual void Refresh() override
    {
        double totalProfit = buyTotalProfit + sellTotalProfit;
        
        // 总盈亏显示，根据盈亏设置颜色
        string totalProfitText = "总盈亏: ";
        if(totalProfit > 0)
        {
            totalProfitText += "+" + DoubleToString(totalProfit, 2);
            lbl_totalprofit.Color(clrLime);  // 盈利显示绿色
        }
        else if(totalProfit < 0)
        {
            totalProfitText += DoubleToString(totalProfit, 2);
            lbl_totalprofit.Color(clrRed);   // 亏损显示红色
        }
        else
        {
            totalProfitText += "0.00";
            lbl_totalprofit.Color(clrBlack);  // 零值显示黑色
        }
        lbl_totalprofit.Text(totalProfitText);
        
        // 买入盈亏显示
        string buyInfoText = "买入盈亏: ";
        if(buyOrderCount > 0)
        {
            if(buyTotalProfit > 0)
            {
                buyInfoText += "+" + DoubleToString(buyTotalProfit, 2);
                lbl_buyinfo.Color(clrLime);  // 盈利显示绿色
            }
            else if(buyTotalProfit < 0)
            {
                buyInfoText += DoubleToString(buyTotalProfit, 2);
                lbl_buyinfo.Color(clrRed);   // 亏损显示红色
            }
            else
            {
                buyInfoText += "0.00";
                lbl_buyinfo.Color(clrBlack);  // 零值显示黑色
            }
        }
        else
        {
            buyInfoText += "0.00";
            lbl_buyinfo.Color(clrBlack);  // 无订单显示黑色
        }
        buyInfoText += "    手数: " + DoubleToString(buyTotalLots, 2) + "    单数: " + IntegerToString(buyOrderCount);
        lbl_buyinfo.Text(buyInfoText);
        
        // 卖出盈亏显示
        string sellInfoText = "卖出盈亏: ";
        if(sellOrderCount > 0)
        {
            if(sellTotalProfit > 0)
            {
                sellInfoText += "+" + DoubleToString(sellTotalProfit, 2);
                lbl_sellinfo.Color(clrLime);  // 盈利显示绿色
            }
            else if(sellTotalProfit < 0)
            {
                sellInfoText += DoubleToString(sellTotalProfit, 2);
                lbl_sellinfo.Color(clrRed);   // 亏损显示红色
            }
            else
            {
                sellInfoText += "0.00";
                lbl_sellinfo.Color(clrBlack);  // 零值显示黑色
            }
        }
        else
        {
            sellInfoText += "0.00";
            lbl_sellinfo.Color(clrBlack);  // 无订单显示黑色
        }
        sellInfoText += "    手数: " + DoubleToString(sellTotalLots, 2) + "    单数: " + IntegerToString(sellOrderCount);
        lbl_sellinfo.Text(sellInfoText);
        
        // 默认下一次加仓手数
        double nextBuyLot = g_InitialLot;
        if(buyOrderCount>0) nextBuyLot = NormalizeDouble(MathFloor(MathPow(g_MultiplierOnLoss, buyOrderCount)) * g_InitialLot, 2);
        double nextSellLot = g_InitialLot;
        if(sellOrderCount>0) nextSellLot = NormalizeDouble(MathFloor(MathPow(g_MultiplierOnLoss, sellOrderCount)) * g_InitialLot, 2);
        edit_next_buy_lot.Text(DoubleToString(nextBuyLot,2));
        edit_next_sell_lot.Text(DoubleToString(nextSellLot,2));
        
        // 更新锁单和解锁按钮状态
        btn_lock.Visible(!g_isLocked && !g_isUnlocking);
        btn_unlock.Visible(g_isLocked && !g_isUnlocking);
        
        // 更新平仓按钮状态
        btn_close_buy.Visible(buyOrderCount > 0);
        btn_close_sell.Visible(sellOrderCount > 0);

        // 获取当前ATR值
        int atrHandle = iATR(_Symbol, TF_Trailing, 14);
        double atrBuffer[];
        if(CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) > 0)
        {
            double currentATR = NormalizeDouble(atrBuffer[0], 2);
            
            // 更新状态显示
            string statusText = DoubleToString(currentATR, 2) + " | ";
            statusText += g_isLocked ? "已锁单" : "未锁单";
            statusText += " | ";
            statusText += g_isUnlocking ? "解锁中" : "未解锁";
            
            lbl_status.Text(statusText);
            
            // 根据状态设置颜色
            if(g_isLocked)
                lbl_status.Color(clrRed);
            else if(g_isUnlocking)
                lbl_status.Color(clrBlue);
            else
                lbl_status.Color(clrBlack);
        }
    }

    // 重写事件处理
    virtual bool OnEvent(const int id, const long &lparam, const double &dparam, const string &sparam) override
    {
        if(id==CHARTEVENT_OBJECT_CLICK)
        {
            if(sparam==btn_modify.Name())
            {
                g_MultiplierOnLoss = StringToDouble(edit_multiplier.Text());
                g_AtrRange = StringToDouble(edit_atrrange.Text());
                g_StopProfit = StringToDouble(edit_stopprofit.Text());
                double newInitialLot = StringToDouble(edit_initial_lot.Text());
                if(newInitialLot > 0.0) g_InitialLot = newInitialLot;
                int newMaxOrderCount = (int)StringToInteger(edit_max_order_count.Text());
                if(newMaxOrderCount > 0) g_MaxOrderCount = newMaxOrderCount;
                
                // 更新参数显示
                edit_multiplier.Text(DoubleToString(g_MultiplierOnLoss,2));
                edit_atrrange.Text(DoubleToString(g_AtrRange,2));
                edit_stopprofit.Text(DoubleToString(g_StopProfit,2));
                edit_initial_lot.Text(DoubleToString(g_InitialLot,2));
                edit_max_order_count.Text(IntegerToString(g_MaxOrderCount));
                
                MessageBox("参数已更新！", "提示", MB_ICONINFORMATION);
                return true;
            }
            else if(sparam==btn_close_buy.Name())
            {
                CloseAllPositions(1, "Manual-B" + IntegerToString(buyBatchCounter));
                return true;
            }
            else if(sparam==btn_close_sell.Name())
            {
                CloseAllPositions(-1, "Manual-S" + IntegerToString(sellBatchCounter));
                return true;
            }
            else if(sparam==btn_add_buy.Name())
            {
                double lot = StringToDouble(edit_next_buy_lot.Text());
                if(lot > 0)
                {
                    trade.Buy(lot, _Symbol, 0, 0, 0, "Manual Buy");
                }
                return true;
            }
            else if(sparam==btn_add_sell.Name())
            {
                double lot = StringToDouble(edit_next_sell_lot.Text());
                if(lot > 0)
                {
                    trade.Sell(lot, _Symbol, 0, 0, 0, "Manual Sell");
                }
                return true;
            }
            else if(sparam==btn_lock.Name())
            {
                // 根据亏损情况决定锁单方向
                if(buyTotalProfit < sellTotalProfit)
                {
                    // Print("手动锁单 - 买入方向");
                    LockPosition(POSITION_TYPE_BUY);
                }
                else
                {
                    // Print("手动锁单 - 卖出方向");
                    LockPosition(POSITION_TYPE_SELL);
                }
                return true;
            }
            else if(sparam==btn_unlock.Name())
            {
                // Print("手动解锁");
                UnlockPosition();
                return true;
            }
        }
        else if(id==CHARTEVENT_OBJECT_ENDEDIT)
        {
            if(sparam == edit_initial_lot.Name())
            {
                double newInitialLot = StringToDouble(edit_initial_lot.Text());
                if(newInitialLot > 0.0) g_InitialLot = newInitialLot;
                edit_initial_lot.Text(DoubleToString(g_InitialLot,2));
            }
            else if(sparam == edit_max_order_count.Name())
            {
                int newMaxOrderCount = (int)StringToInteger(edit_max_order_count.Text());
                if(newMaxOrderCount > 0) g_MaxOrderCount = newMaxOrderCount;
                edit_max_order_count.Text(IntegerToString(g_MaxOrderCount));
            }
        }
        return CCustomDialog::OnEvent(id, lparam, dparam, sparam);
    }

    // 构造函数
    CMartingalePanel()
    {
        SetFontSize(font_size);  // 设置字体大小
        
        // 初始化参数显示
        edit_multiplier.Text(DoubleToString(g_MultiplierOnLoss,2));
        edit_atrrange.Text(DoubleToString(g_AtrRange,2));
        edit_stopprofit.Text(DoubleToString(g_StopProfit,2));
        edit_initial_lot.Text(DoubleToString(g_InitialLot,2));
        edit_max_order_count.Text(IntegerToString(g_MaxOrderCount));
    }
};

CMartingalePanel *g_panel = NULL;

//+------------------------------------------------------------------+
//| 日志控制函数                                                      |
//+------------------------------------------------------------------+
void SetupLogging()
{
    // 调用头文件中的日志初始化函数
    InitializeLogging(LogLevel, EnableFileLog, EnableConsoleLog);
}

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
    // 记录启动时间
    g_startTime = TimeCurrent();
    
    // Initialize global variables with input parameters
    g_InitialLot = InitialLot;
    g_MaxOrderCount = MaxOrderCount;
    g_AtrRange = AtrRange;  // 初始化ATR倍率
    g_StopProfit = StopProfit;  // 初始化止盈点数
    g_MultiplierOnLoss = MultiplierOnLoss; // 初始化亏损后倍数
    
    // 初始化日志系统
    SetupLogging();
    
    LogInfo("=== Martingale EA 初始化开始 ===", EnableConsoleLog);
    LogInfo("EA版本: 1.0", EnableConsoleLog);
    LogInfo("交易品种: " + _Symbol, EnableConsoleLog);
    LogInfo("时间框架: " + EnumToString(Period()), EnableConsoleLog);
    LogInfo("初始手数: " + DoubleToString(g_InitialLot, 2), EnableConsoleLog);
    LogInfo("最大订单数: " + IntegerToString(g_MaxOrderCount), EnableConsoleLog);
    LogInfo("ATR倍率: " + DoubleToString(g_AtrRange, 2), EnableConsoleLog);
    LogInfo("止盈点数: " + DoubleToString(g_StopProfit, 0), EnableConsoleLog);
    LogInfo("亏损倍数: " + DoubleToString(g_MultiplierOnLoss, 2), EnableConsoleLog);

    // 检查是否有锁单
    for(int i = 0; i < PositionsTotal(); i++)
    {
        if(PositionSelectByTicket(PositionGetTicket(i)))
        {
            if(StringFind(PositionGetString(POSITION_COMMENT), "lock") >= 0)
            {
                g_isLocked = true;
                ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
                g_lockType = (posType == POSITION_TYPE_BUY ? POSITION_TYPE_SELL : POSITION_TYPE_BUY);
                g_lockLots = PositionGetDouble(POSITION_VOLUME);
                g_lockTicket = PositionGetTicket(i);
                g_lockProfit = PositionGetDouble(POSITION_PROFIT);
                g_lockStartTime = 0;  // 重置锁单开始时间
                break;
            }
        }
    }


    // 初始化批次记录数组
    buyBatches = new CArrayObj;
    sellBatches = new CArrayObj;
    orderRelations = new CArrayObj;

    // 获取当前时间框架
    TF_Trailing = GetTimeframe(Period());
    if (TF_Trailing == 0)
    {
        LogError("错误：不支持当前时间框架", EnableConsoleLog);
        return INIT_FAILED;
    }

    // 获取交易信息
    stopLevel = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
    minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
    maxLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
    lotStep = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
    spread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);

    // 创建图表标签
    CreateLabels();

    trade.SetExpertMagicNumber(MagicNumber);

    g_panel = new CMartingalePanel;
    if(!g_panel.Create(ChartID(), "MartingalePanel", 0, 10, 10, 530, 600))
    {
        LogError("面板创建失败", EnableConsoleLog);
        delete g_panel; g_panel = NULL;
        return INIT_FAILED;
    }
    
    // 确保面板显示在最上层
    g_panel.BringToTop();
    
    // 设置定时器更新面板
    EventSetTimer(1);
    
    // 强制更新图表
    ChartRedraw();
    
    // 初始化布林带指标
    g_bbHandle = iBands(_Symbol, PERIOD_CURRENT, BB_Period, 0, BB_Deviation, PRICE_CLOSE);
    if(g_bbHandle == INVALID_HANDLE)
    {
        LogError("布林带指标初始化失败", EnableConsoleLog);
        return INIT_FAILED;
    }

    // 初始化均线指标
    g_ma20Handle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);
    if(g_ma20Handle == INVALID_HANDLE)
    {
        LogError("20周期均线指标初始化失败", EnableConsoleLog);
        return INIT_FAILED;
    }
    // 设置20均线显示属性
    ChartIndicatorAdd(0, 0, g_ma20Handle);
    PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
    PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrGreen);  // 默认绿色
    PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 2);  // 加粗线条便于观察

    /* 暂时注释掉50均线
    g_ma50Handle = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_SMA, PRICE_CLOSE);
    if(g_ma50Handle == INVALID_HANDLE)
    {
        Print("50周期均线指标初始化失败");
        return INIT_FAILED;
    }
    // 设置50均线显示属性
    ChartIndicatorAdd(0, 0, g_ma50Handle);
    PlotIndexSetInteger(0, PLOT_DRAW_TYPE, DRAW_LINE);
    PlotIndexSetInteger(0, PLOT_LINE_COLOR, clrRed);
    PlotIndexSetInteger(0, PLOT_LINE_WIDTH, 1);
    */
    
    // 初始化ATR指标句柄
    g_atrHandle = iATR(_Symbol, PERIOD_CURRENT, 14);
    if(g_atrHandle == INVALID_HANDLE)
    {
        LogError("ATR指标初始化失败!", EnableConsoleLog);
        return INIT_FAILED;
    }
    
    LogInfo("=== EA初始化完成 ===", EnableConsoleLog);
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Expert tick function                                              |
//+------------------------------------------------------------------+
void OnTick()
{
    // 更新全局ATR值
    double atrBuffer[1];
    if(CopyBuffer(g_atrHandle, 0, 0, 1, atrBuffer) > 0)
        g_atr = atrBuffer[0];
    else
        g_atr = 0;

    // 计算 ATR 值
    CalculateStepSize();

    // 计算订单统计信息
    CalculateOrderStats();

    // 更新最大回撤
    UpdateMaxDrawdown();

    // 检查锁单和解锁条件
    if(!g_isLocked && !g_isUnlocking)
    {
        CheckLockCondition();
    }
    else if(g_isLocked)
    {
        //暂时不自动解锁
        // CheckUnlockCondition();
    }
    
    // 如果处于锁单状态，直接返回
    if(g_isLocked)
    {
        return;
    }
    
    // 如果处于解锁状态，处理保本平仓
    if(g_isUnlocking)
    {
        HandleBreakEven();
    }else{
        //处理移动止盈 解锁后不执行
        HandleTrailingStop();
        // 处理止盈平仓
        HandleTakeProfit();
        
        HandleStopLoss();
    }

    // 开仓和加仓逻辑
    OpenOrAddPosition();

    // 修改挂单
    ModifyOrders();
    
    // 更新趋势可视化
    UpdateTrendVisualization();
}

// 计算加仓步长
void CalculateStepSize()
{
    int atrHandle = iATR(_Symbol, TF_Trailing, 14);
    // 获取最新 ATR 值
    double atrBuffer[];
    if (CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) < 1)
    {
        // Print("获取 ATR 失败！错误代码: ", GetLastError());
        return;
    }
    double atrValue = atrBuffer[0];
    if(atrValue<0.5 && StringFind(_Symbol, "GBPUSDm") < 0 && StringFind(_Symbol, "USDJPAm") < 0){
      atrValue=0.8;
    }


    buyStepPrice = g_AtrRange * atrValue; // 使用g_AtrRange而不是AtrRange
    
    sellStepPrice = buyStepPrice;       // 保持一致
}

//+------------------------------------------------------------------+
//| 更新趋势可视化                                                     |
//+------------------------------------------------------------------+
void UpdateTrendVisualization()
{
    datetime currentTime = TimeCurrent();
    
    // 检查是否需要更新（每分钟更新一次）
    if(currentTime - g_lastTrendUpdate < 60)
    {
        return; // 还没到更新时间
    }
    
    // 更新时间戳
    g_lastTrendUpdate = currentTime;
    
    // 初始化智能加仓数据（买入方向）
    bool buyTrendStrong = false;
    if(InitializeSmartAddData(true))
    {
        // 使用虚拟订单数量5来判断趋势，这样可以获得标准的趋势强度判断
        buyTrendStrong = IsTrendTooStrong(true, 5);
    }
    
    // 初始化智能加仓数据（卖出方向）
    bool sellTrendStrong = false;
    if(InitializeSmartAddData(false))
    {
        // 使用虚拟订单数量5来判断趋势
        sellTrendStrong = IsTrendTooStrong(false, 5);
    }
    
    // 根据趋势强度设置颜色
    color ma20Color = clrGreen;  // 默认绿色（趋势不强）
    
    if(buyTrendStrong && sellTrendStrong)
    {
        // 双向都是强趋势，显示深红色
        ma20Color = clrDarkRed;
    }
    else if(buyTrendStrong || sellTrendStrong)
    {
        // 单向强趋势，显示红色
        ma20Color = clrRed;
    }
    else
    {
        // 趋势不强，显示绿色
        ma20Color = clrGreen;
    }
    
    // 在图表上显示趋势信息
    DisplayTrendInfo(buyTrendStrong, sellTrendStrong);
}



//+------------------------------------------------------------------+
//| 在图表上显示趋势信息                                               |
//+------------------------------------------------------------------+
void DisplayTrendInfo(bool buyTrendStrong, bool sellTrendStrong)
{
    // 创建或更新趋势信息标签
    string labelName = "TrendInfo";
    string trendText = "";
    color textColor = clrWhite;
    
    // 构建简化的趋势信息文本（不显示持仓信息）
    trendText = "趋势状态: 买入" + (buyTrendStrong ? "强" : "弱") + " | 卖出" + (sellTrendStrong ? "强" : "弱");
    
    // 设置文本颜色
    if(buyTrendStrong && sellTrendStrong)
        textColor = clrDarkRed;
    else if(buyTrendStrong || sellTrendStrong)
        textColor = clrRed;
    else
        textColor = clrGreen;
    
    // 删除旧标签
    ObjectDelete(0, labelName);
    
    // 创建新标签 - 左上角位置
    if(ObjectCreate(0, labelName, OBJ_LABEL, 0, 0, 0))
    {
        ObjectSetInteger(0, labelName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
        ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, 10);  // 距离左边缘
        ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, 30);  // 距离顶部
        ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 10);   // 稍大字体便于观察
        ObjectSetString(0, labelName, OBJPROP_FONT, "Arial Bold");
        ObjectSetInteger(0, labelName, OBJPROP_COLOR, textColor);
        ObjectSetInteger(0, labelName, OBJPROP_BACK, false);
        ObjectSetInteger(0, labelName, OBJPROP_SELECTABLE, false);
        ObjectSetInteger(0, labelName, OBJPROP_HIDDEN, true);
        ObjectSetString(0, labelName, OBJPROP_TEXT, trendText);
        
        // 强制刷新图表
        ChartRedraw(0);
    }
}

//+------------------------------------------------------------------+
//| 获取标准时间框架函数                                               |
//+------------------------------------------------------------------+
int GetTimeframe(int timeframe)
{
    if (timeframe > 43200)
        return 0;
    if (timeframe > 10080)
        return 43200; // 月线
    if (timeframe > 1440)
        return 10080; // 周线
    if (timeframe > 240)
        return 1440; // 日线
    if (timeframe > 60)
        return 240; // 4小时
    if (timeframe > 30)
        return 60; // 1小时
    if (timeframe > 15)
        return 30; // 30分钟
    if (timeframe > 5)
        return 15; // 15分钟
    if (timeframe > 1)
        return 5; // 5分钟
    if (timeframe == 1)
        return 1; // 1分钟
    if (timeframe == 0)
        return Period();
    return 0;
}

//+------------------------------------------------------------------+
//| 创建图表标签                                                       |
//+------------------------------------------------------------------+
void CreateLabels()
{
    chartCorner = font_size + font_size / 2;

    // 创建账户余额标签
    CreateLabel("Balance", chartCorner);
    chartCorner += font_size * 2;

    // 创建账户净值标签
    CreateLabel("Equity", chartCorner);
    chartCorner += font_size * 2;

    // 创建可用保证金标签
    CreateLabel("FreeMargin", chartCorner);
    chartCorner += font_size * 2;

    // 创建买入盈亏标签
    CreateLabel("ProfitB", chartCorner);
    chartCorner += font_size * 2;

    // 创建卖出盈亏标签
    CreateLabel("ProfitS", chartCorner);
    chartCorner += font_size * 2;

    // 创建总盈亏标签
    CreateLabel("Profit", chartCorner);
    chartCorner += font_size * 2;
}

//+------------------------------------------------------------------+
//| 创建单个标签                                                       |
//+------------------------------------------------------------------+
void CreateLabel(string name, int y_distance)
{
    ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
    ObjectSetInteger(0, name, OBJPROP_CORNER, 1);
    ObjectSetInteger(0, name, OBJPROP_XDISTANCE, 5);
    ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y_distance);
    ObjectSetInteger(0, name, OBJPROP_FONTSIZE, font_size);
    ObjectSetString(0, name, OBJPROP_FONT, "Arial");
    ObjectSetInteger(0, name, OBJPROP_COLOR, clrWhite);
}

//+------------------------------------------------------------------+
//| 统计订单信息                                                       |
//+------------------------------------------------------------------+
void CalculateOrderStats()
{
    // 重置所有统计数据
    buyTotalLots = 0;
    sellTotalLots = 0;
    buyTotalValue = 0;
    sellTotalValue = 0;
    buyTotalProfit = 0;
    sellTotalProfit = 0;
    highestBuyPrice = 0;
    lowestBuyPrice = 0;
    highestSellPrice = 0;
    lowestSellPrice = 0;
    buyOrderCount = 0;
    sellOrderCount = 0;

    // 重置当前挂单数量
    buyPendingOrders = 0;
    sellPendingOrders = 0;

    // 遍历所有持仓
    for (int i = PositionsTotal() - 1; i >= 0; i--)
    {
        if (PositionSelectByTicket(PositionGetTicket(i)))
        {
            if (PositionGetString(POSITION_SYMBOL) == Symbol() &&
                PositionGetInteger(POSITION_MAGIC) == MagicNumber)
            {
                double posLots = PositionGetDouble(POSITION_VOLUME);
                double posPrice = PositionGetDouble(POSITION_PRICE_OPEN);
                double posProfit = PositionGetDouble(POSITION_PROFIT);
                double posSwap = PositionGetDouble(POSITION_SWAP);

                if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
                {
                    buyOrderCount++;
                    buyTotalLots += posLots;
                    buyTotalValue += posPrice * posLots;
                    buyTotalProfit += posProfit + posSwap;

                    if (highestBuyPrice < posPrice || highestBuyPrice == 0)
                        highestBuyPrice = posPrice;
                    if (lowestBuyPrice > posPrice || lowestBuyPrice == 0)
                        lowestBuyPrice = posPrice;
                }
                else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
                {
                    sellOrderCount++;
                    sellTotalLots += posLots;
                    sellTotalValue += posPrice * posLots;
                    sellTotalProfit += posProfit + posSwap;

                    if (highestSellPrice < posPrice || highestSellPrice == 0)
                        highestSellPrice = posPrice;
                    if (lowestSellPrice > posPrice || lowestSellPrice == 0)
                        lowestSellPrice = posPrice;
                }
            }
        }
    }

    // 遍历所有挂单
    for (int i = OrdersTotal() - 1; i >= 0; i--)
    {
        ulong ticket = OrderGetTicket(i); // 获取订单ticket
        if (ticket > 0)                   // 如果成功获取ticke
        {
            if (OrderSelect(ticket))
            {

                if (OrderGetString(ORDER_SYMBOL) == Symbol() &&
                    OrderGetInteger(ORDER_MAGIC) == MagicNumber)
                {

                    ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
                    if (orderType == ORDER_TYPE_BUY_STOP)
                    {
                        buyPendingOrders++;
                        buyStopTicket = OrderGetTicket(i); // 存储买入挂单票据
                    }
                    else if (orderType == ORDER_TYPE_SELL_STOP)
                    {
                        sellPendingOrders++;
                        sellStopTicket = OrderGetTicket(i); // 存储卖出挂单票据
                    }
                }
            }
        }
    }

    // 计算平均价格
    if (buyTotalLots > 0)
        buyAveragePrice = NormalizeDouble(buyTotalValue / buyTotalLots, _Digits);
    if (sellTotalLots > 0)
        sellAveragePrice = NormalizeDouble(sellTotalValue / sellTotalLots, _Digits);

    // 更新图形标记
    UpdateChartObjects();
}

//+------------------------------------------------------------------+
//| 更新图表对象                                                       |
//+------------------------------------------------------------------+
void UpdateChartObjects()
{
    ObjectDelete(0, "Avg_Buy");
    ObjectDelete(0, "Avg_Sell");
    if (buyOrderCount > 0) {
        ObjectCreate(0, "Avg_Buy", OBJ_HLINE, 0, 0, buyAveragePrice);
        ObjectSetInteger(0, "Avg_Buy", OBJPROP_COLOR, clrBlue);
        ObjectSetInteger(0, "Avg_Buy", OBJPROP_STYLE, STYLE_SOLID);
        ObjectSetInteger(0, "Avg_Buy", OBJPROP_WIDTH, 2);
        ObjectSetInteger(0, "Avg_Buy", OBJPROP_BACK, true);
        ObjectSetInteger(0, "Avg_Buy", OBJPROP_SELECTABLE, false);
        ObjectSetInteger(0, "Avg_Buy", OBJPROP_HIDDEN, true);
        ObjectSetString(0, "Avg_Buy", OBJPROP_TOOLTIP, "买入均价: " + DoubleToString(buyAveragePrice, _Digits));
    }
    if (sellOrderCount > 0) {
        ObjectCreate(0, "Avg_Sell", OBJ_HLINE, 0, 0, sellAveragePrice);
        ObjectSetInteger(0, "Avg_Sell", OBJPROP_COLOR, clrRed);
        ObjectSetInteger(0, "Avg_Sell", OBJPROP_STYLE, STYLE_SOLID);
        ObjectSetInteger(0, "Avg_Sell", OBJPROP_WIDTH, 2);
        ObjectSetInteger(0, "Avg_Sell", OBJPROP_BACK, true);
        ObjectSetInteger(0, "Avg_Sell", OBJPROP_SELECTABLE, false);
        ObjectSetInteger(0, "Avg_Sell", OBJPROP_HIDDEN, true);
        ObjectSetString(0, "Avg_Sell", OBJPROP_TOOLTIP, "卖出均价: " + DoubleToString(sellAveragePrice, _Digits));
    }
}

//+------------------------------------------------------------------+
//| 处理止盈平仓                                                       |
//+------------------------------------------------------------------+
void HandleTakeProfit()
{
    // 检查买入止盈
    if (buyTotalProfit >= g_StopProfit * buyOrderCount && buyTotalLots > 0)  // 使用g_StopProfit
    {
        // Print("买入止盈触发，当前盈利: ", buyTotalProfit);
        CloseAllPositions(1, "TP-B" + IntegerToString(buyBatchCounter));
    }

    // 检查卖出止盈
    if (sellTotalProfit >= g_StopProfit * sellOrderCount && sellTotalLots > 0)  // 使用g_StopProfit
    {
        // Print("卖出止盈触发，当前盈利: ", sellTotalProfit);
        CloseAllPositions(-1, "TP-S" + IntegerToString(sellBatchCounter));
    }

    // 检查总盈利止盈
    double totalProfit = buyTotalProfit + sellTotalProfit;
    if (totalProfit >= CloseAll)
    {
        // Print("总盈利止盈触发，当前总盈利: ", totalProfit);
        CloseAllPositions(0, "TP-ALL");
    }
}

//+------------------------------------------------------------------+
//| 处理止损平仓                                                       |
//+------------------------------------------------------------------+
void HandleStopLoss()
{
    // 检查买入止损
    if (buyTotalProfit <= StopLoss)
    {
        // Print("买入止损触发，当前亏损: ", buyTotalProfit);
        CloseAllPositions(1, "SL-B" + IntegerToString(buyBatchCounter));
    }

    // 检查卖出止损
    if (sellTotalProfit <= StopLoss)
    {
        // Print("卖出止损触发，当前亏损: ", sellTotalProfit);
        CloseAllPositions(-1, "SL-S" + IntegerToString(sellBatchCounter));
    }
}

//+------------------------------------------------------------------+
//| 处理移动止盈                                                       |
//+------------------------------------------------------------------+
void HandleTrailingStop()
{
     // 临时存储当前批次信息
    MqlTick latest_price;
    if (!SymbolInfoTick(_Symbol, latest_price))
        return;

    double ask = latest_price.ask;
    double bid = latest_price.bid;

    // 获取动态止损价格
    double buyStopLoss = GetDynamicStopLoss(1, bid, stopLevel);
    double sellStopLoss = GetDynamicStopLoss(-1, ask, stopLevel);

    // 获取当前币种的最小获利点数
    double currentMinProfit = GetMinProfit();

    bool buyBatchModified = false;
    bool sellBatchModified = false;

    // 遍历所有持仓
    for (int i = PositionsTotal() - 1; i >= 0; i--)
    {
        if (PositionSelectByTicket(PositionGetTicket(i)))
        {
            if (PositionGetString(POSITION_SYMBOL) == Symbol() &&
                PositionGetInteger(POSITION_MAGIC) == MagicNumber)
            {
                double posLots = PositionGetDouble(POSITION_VOLUME);
                double posPrice = PositionGetDouble(POSITION_PRICE_OPEN);
                double posProfit = PositionGetDouble(POSITION_PROFIT);
                double currentStopLoss = PositionGetDouble(POSITION_SL);

                if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
                {
                    // 检查是否需要修改止损
                    if ((buyStopLoss > currentStopLoss || currentStopLoss == 0) &&
                        buyStopLoss >= buyAveragePrice + currentMinProfit)
                    {
                        trade.PositionModify(PositionGetTicket(i), buyStopLoss, 0);
                        buyBatchModified = true;
                    }
                }
                else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
                {
                    // 检查是否需要修改止损
                    if ((sellStopLoss < currentStopLoss || currentStopLoss == 0) &&
                        sellStopLoss <= sellAveragePrice - currentMinProfit)
                    {
                        trade.PositionModify(PositionGetTicket(i), sellStopLoss, 0);
                        sellBatchModified = true;
                    }
                }
            }
        }
    }
}

//+------------------------------------------------------------------+
//| 处理移动止损                                                       |
//+------------------------------------------------------------------+
void HandleTrailingStopLoss()
{
    // 如果没有任何批次达到最大订单数，直接返回
    if (maxBuyTime == 0 && maxSellTime == 0)
        return;

    MqlTick latest_price;
    if (!SymbolInfoTick(_Symbol, latest_price))
        return;

    double ask = latest_price.ask;
    double bid = latest_price.bid;
    datetime now = TimeCurrent();

    // 计算ATR
    int atrHandle = iATR(_Symbol, TF_Trailing, 14);
    double atrBuffer[];
    if (CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) < 1)
    {
        // Print("获取 ATR 失败！错误代码: ", GetLastError());
        return;
    }
    double atrValue = atrBuffer[0];
    if(atrValue < 0.5) atrValue = 0.5;

    // 遍历所有持仓
    for (int i = PositionsTotal() - 1; i >= 0; i--)
    {
        if (PositionSelectByTicket(PositionGetTicket(i)))
        {
            if (PositionGetString(POSITION_SYMBOL) == Symbol() &&
                PositionGetInteger(POSITION_MAGIC) == MagicNumber)
            {
                double posLots = PositionGetDouble(POSITION_VOLUME);
                double posPrice = PositionGetDouble(POSITION_PRICE_OPEN);
                double posProfit = PositionGetDouble(POSITION_PROFIT);
                ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

                // 检查是否达到最大订单数量
                if (posType == POSITION_TYPE_BUY && buyOrderCount >= MaxOrderCount && maxBuyTime > 0)
                {
                    // 30分钟后保本
                    if ((now - maxBuyTime) >= 30 * 60)
                    {
                        // 如果当前利润大于0，直接平仓
                        if (buyTotalProfit > 0)
                        {
                            Alert("警告：买单30分钟后保本平仓触发！\n当前利润: ", buyTotalProfit);
                            CloseAllPositions(1, "TSL-B" + IntegerToString(buyBatchCounter));
                            // Print("买单30分钟后保本平仓，当前利润: ", buyTotalProfit);
                        }
                    }

                    // 60分钟后且亏损大于800时移动止损
                    if ((now - maxBuyTime) >= 60 * 60 && buyMaxDrawdown < -400)
                    {
                        double newStopLoss = NormalizeDouble(bid - 0.2 * atrValue, _Digits);
                        double currentStopLoss = PositionGetDouble(POSITION_SL);
                        
                        // 检查是否满足最小间距要求
                        if ((newStopLoss > currentStopLoss || currentStopLoss == 0) && 
                            (bid - newStopLoss) >= stopLevel * _Point)
                        {
                            // Print("警告：买单移动止损触发！\n当前价: ", bid, "\n新止损价: ", newStopLoss);
                            trade.PositionModify(PositionGetTicket(i), newStopLoss, 0);
                            // Print("买单移动止损，新止损价: ", newStopLoss);
                        }
                    }
                }
                else if (posType == POSITION_TYPE_SELL && sellOrderCount >= MaxOrderCount && maxSellTime > 0)
                {
                  
                    // 30分钟后保本
                    if ((now - maxSellTime) >= 30 * 60)
                    {
             
                        // 如果当前利润大于0，直接平仓
                        if (sellTotalProfit > 0)
                        {
                            Alert("警告：卖单30分钟后保本平仓触发！\n当前利润: ", sellTotalProfit);
                            CloseAllPositions(-1, "TSL-S" + IntegerToString(sellBatchCounter));
                            // Print("卖单30分钟后保本平仓，当前利润: ", sellTotalProfit);
                        }
                    }

                    // 60分钟后且亏损大于800时移动止损
                    if ((now - maxSellTime) >= 60 * 60 && sellMaxDrawdown < -400)
                    {
                        double newStopLoss = NormalizeDouble(ask + 0.2 * atrValue, _Digits);
                        double currentStopLoss = PositionGetDouble(POSITION_SL);
                        
                        // 检查是否满足最小间距要求
                        if ((newStopLoss < currentStopLoss || currentStopLoss == 0) && 
                            (newStopLoss - ask) >= stopLevel * _Point)
                        {
                            // Print("警告：卖单移动止损触发！\n当前价: ", ask, "\n新止损价: ", newStopLoss);
                            trade.PositionModify(PositionGetTicket(i), newStopLoss, 0);
                            // Print("卖单移动止损，新止损价: ", newStopLoss);
                        }
                    }
                }
            }
        }
    }
}

// 修改函数来获取基于ATR的首步值
double GetFirstStep()
{
    // 获取ATR指标句柄
    int atrHandle = iATR(_Symbol, TF_Trailing, 14);
    if(atrHandle == INVALID_HANDLE)
    {
        // Print("获取ATR指标失败");
        return 0.0;
    }

    // 获取ATR值
    double atrBuffer[];
    if(CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) < 1)
    {
        // Print("复制ATR数据失败");
        return 0.0;
    }

    double atrValue = atrBuffer[0];
    
    // 确保ATR值不会太小
    // if(atrValue < 0.5)
    //     atrValue = 0.5;

    // 根据不同的交易品种调整ATR值
    string symbol = _Symbol;
    if(StringFind(symbol, "BTC") >= 0){
        if(atrValue < 50){
          atrValue = 50;
        }
        return atrValue*0.3;  // 比特币直接使用ATR值
    }else if(StringFind(symbol, "XAU") >= 0){
        if(atrValue < 0.5){
           atrValue = 0.5;
        }
         
        return atrValue*0.3/ 100.0;   // 黄金将ATR值除以100
    }else if(StringFind(symbol, "EUR") >= 0 || StringFind(symbol, "GBP") >= 0 || 
            StringFind(symbol, "USD") >= 0 || StringFind(symbol, "JPY") >= 0)
    {
        // 对于主要货币对，根据点值计算
       // double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
        //double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
       // double pointsPerDollar = tickValue / tickSize;
        //return NormalizeDouble(atrValue * pointsPerDollar / 200.0, 2); // 假设ATR值是基于比特币200点的基准
        return 0.3*atrValue;
    }
    else
    {
        // 其他货币对，使用默认计算方式
        double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
        double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
        double pointsPerDollar = tickValue / tickSize;
        return NormalizeDouble(atrValue * pointsPerDollar / 200.0, 2); // 假设ATR值是基于比特币200点的基准
    }
}

//挂单参考上次挂单位置
void OpenOrAddPosition()
{
    MqlTick latest_price;
    if (!SymbolInfoTick(_Symbol, latest_price))
        return;

    double ask = latest_price.ask;
    double bid = latest_price.bid;
    double newOrderLots;
    double newOrderPrice;

    // 买入逻辑
    if (Buy && buyPendingOrders == 0 && buyOrderCount < g_MaxOrderCount && IsPriceBelowMA())
    {
        // 基础前提条件：当前价格必须低于最低买入价才考虑智能加仓
        if(buyOrderCount >= SmartAddStartLevel-1 && ask >= lowestBuyPrice) {
            // Print("[SmartAdd] 买入基础条件不满足 - 当前价格:", ask, " 最低买入价:", lowestBuyPrice);
            return;
        }
        
        // 先计算挂单价格
        double atr = g_atr;
        newOrderPrice = (buyOrderCount == 0) ? CalculateAddOrderPrice(ask, 0, ORDER_TYPE_BUY_STOP) : NormalizeDouble(lowestBuyPrice - g_AtrRange * atr, _Digits);
        
        // 基础价格有效性检查（所有挂单都必须通过）
        if(!IsValidOrderPrice(newOrderPrice, ask, ORDER_TYPE_BUY_STOP)) {
            return; // 价格无效，直接返回
        }
        
        // 智能加仓条件检查（仅对第5单及以后生效）
        if(buyOrderCount >= SmartAddStartLevel-1) {
            if(!CanAddSmartOrder(true, buyOrderCount, lowestBuyPrice)) {
                return; // 不满足智能加仓条件，直接返回
            }
        }
        
        // 计算手数
        if(buyOrderCount < SmartAddStartLevel) {
            // 前5单使用标准马丁倍率
            newOrderLots = NormalizeDouble(MathPow(g_MultiplierOnLoss, buyOrderCount) * g_InitialLot, 2);
        } else {
            // 第6单开始使用智能手数计算（不输出详细日志）
            double baseLot = (lastBuyLot > 0) ? lastBuyLot : NormalizeDouble(MathPow(g_MultiplierOnLoss, buyOrderCount-1) * g_InitialLot, 2);
            if(SmartLotMethod == 1) {
                newOrderLots = CalculateSmartLotSize(true, lowestBuyPrice, ask, atr, baseLot);
            } else {
                newOrderLots = CalculateSimpleSmartLot(true, lowestBuyPrice, ask, atr, baseLot);
            }
        }
        
        // 打印买入开仓决策参数
        // PrintFormat("[买入决策] 第%d单 | 当前价:%.5f | 挂单价:%.5f | 手数:%.2f | 智能判断:允许", 
        //     buyOrderCount+1, ask, newOrderPrice, newOrderLots);
        
        if(newOrderLots < AccountInfoDouble(ACCOUNT_MARGIN_FREE) / SymbolInfoDouble(_Symbol, SYMBOL_MARGIN_INITIAL))
        {
            MqlDateTime timeStruct; TimeToStruct(TimeCurrent(), timeStruct);
            if (!sj || (sj && timeStruct.hour > star && timeStruct.hour < end))
            {
                if (trade.BuyStop(newOrderLots, newOrderPrice, _Symbol, 0, 0, ORDER_TIME_GTC, 0, "Martingale EA"))
                {
                    // 不在这里更新lastBuyLot，等待实际成交时更新
                    // lastBuyLot = newOrderLots;  // 删除这行，防止挂单失败时错误更新
                    PrintFormat("买入挂单 #%d 创建成功, 手数: %.2f, 价格: %.5f", OrderGetTicket(OrdersTotal() - 1), newOrderLots, newOrderPrice);
                }
            }
        }
    }

    // 卖出逻辑
    if (Sell && sellPendingOrders == 0 && sellOrderCount < g_MaxOrderCount && IsPriceAboveMA())
    {
        // 基础前提条件：当前价格必须高于最高卖出价才考虑智能加仓
        if(sellOrderCount >= SmartAddStartLevel-1 && bid <= highestSellPrice) {
            // Print("[SmartAdd] 卖出基础条件不满足 - 当前价格:", bid, " 最高卖出价:", highestSellPrice);
            return;
        }
        
        // 先计算挂单价格
        double atr = g_atr;
        newOrderPrice = (sellOrderCount == 0) ? CalculateAddOrderPrice(bid, 0, ORDER_TYPE_SELL_STOP) : NormalizeDouble(highestSellPrice + g_AtrRange * atr, _Digits);
        
        // 基础价格有效性检查（所有挂单都必须通过）
        if(!IsValidOrderPrice(newOrderPrice, bid, ORDER_TYPE_SELL_STOP)) {
            return; // 价格无效，直接返回
        }
        
        // 智能加仓条件检查（仅对第5单及以后生效）
        if(sellOrderCount >= SmartAddStartLevel-1) {
            if(!CanAddSmartOrder(false, sellOrderCount, highestSellPrice)) {
                return; // 不满足智能加仓条件，直接返回
            }
        }
        
        // 计算手数
        if(sellOrderCount < SmartAddStartLevel) {
            // 前5单使用标准马丁倍率
            newOrderLots = NormalizeDouble(MathPow(g_MultiplierOnLoss, sellOrderCount) * g_InitialLot, 2);
        } else {
            // 第6单开始使用智能手数计算（不输出详细日志）
            double baseLot = (lastSellLot > 0) ? lastSellLot : NormalizeDouble(MathPow(g_MultiplierOnLoss, sellOrderCount-1) * g_InitialLot, 2);
            if(SmartLotMethod == 1) {
                newOrderLots = CalculateSmartLotSize(false, highestSellPrice, bid, atr, baseLot);
            } else {
                newOrderLots = CalculateSimpleSmartLot(false, highestSellPrice, bid, atr, baseLot);
            }
        }
        
        // 打印卖出开仓决策参数
        // PrintFormat("[卖出决策] 第%d单 | 当前价:%.5f | 挂单价:%.5f | 手数:%.2f | 智能判断:允许", 
        //     sellOrderCount+1, bid, newOrderPrice, newOrderLots);
        
        if(newOrderLots < AccountInfoDouble(ACCOUNT_MARGIN_FREE) / SymbolInfoDouble(_Symbol, SYMBOL_MARGIN_INITIAL))
        {
            MqlDateTime timeStruct; TimeToStruct(TimeCurrent(), timeStruct);
            if (!sj || (sj && timeStruct.hour > star && timeStruct.hour < end))
            {
                if (trade.SellStop(newOrderLots, newOrderPrice, _Symbol, 0, 0, ORDER_TIME_GTC, 0, "Martingale EA"))
                {
                    // 不在这里更新lastSellLot，等待实际成交时更新
                    // lastSellLot = newOrderLots;  // 删除这行，防止挂单失败时错误更新
                    PrintFormat("卖出挂单 #%d 创建成功, 手数: %.2f, 价格: %.5f", OrderGetTicket(OrdersTotal() - 1), newOrderLots, newOrderPrice);
                }
            }
        }
    }
}

// 修改ModifyOrders函数 移动参考市场价 https://yun.dwxxx.com/#/login
void ModifyOrders()
{
    MqlTick latest_price;
    if (!SymbolInfoTick(_Symbol, latest_price))
        return;

    double ask = latest_price.ask;
    double bid = latest_price.bid;
    
    // 获取挂单距离
    double orderDistance = GetOrderDistance();
    // 设置移动步长为挂单距离的三分之一
    double stepTrallOrders = orderDistance / 3.0;

    // 修改买入挂单
    if (buyStopTicket != 0 && OrderSelect(buyStopTicket))
    {
        double buyOpenPrice = OrderGetDouble(ORDER_PRICE_OPEN);
        double newOrderPrice = NormalizeDouble(buyOpenPrice - stepTrallOrders, _Digits);

        // Print("buyOpenPrice: ", buyOpenPrice, " newOrderPrice: ", newOrderPrice, " orderDistance: ", orderDistance, " ask: ", ask);
        // 只有当新价格与当前市场价格保持足够距离时才修改
        if (newOrderPrice - ask >= orderDistance)
        {
            if (!trade.OrderModify(buyStopTicket, newOrderPrice, 0, 0, 0, clrWhite))
            {
                // Print("Error ", GetLastError(), "   Order Modify Buy   OOP ", buyOpenPrice, "->", newOrderPrice);
            }
        }
    }

    // 修改卖出挂单
    if (sellStopTicket != 0 && OrderSelect(sellStopTicket))
    {
        double sellOpenPrice = OrderGetDouble(ORDER_PRICE_OPEN);
        double newOrderPrice = NormalizeDouble(sellOpenPrice + stepTrallOrders, _Digits);

        // 只有当新价格与当前市场价格保持足够距离时才修改
        if (bid - newOrderPrice >= orderDistance)
        {
            // Print("sellOpenPrice: ", sellOpenPrice, " newOrderPrice: ", newOrderPrice, " orderDistance: ", orderDistance, " bid: ", bid);
            if (!trade.OrderModify(sellStopTicket, newOrderPrice, 0, 0, 0, clrWhite))
            {
                // Print("Error ", GetLastError(), "   Order Modify Sell   OOP ", sellOpenPrice, "->", newOrderPrice);
            }
        }
    }
}

//+------------------------------------------------------------------+
//| 更新标签显示                                                       |
//+------------------------------------------------------------------+
void UpdateLabels()
{
    double balance = AccountInfoDouble(ACCOUNT_BALANCE);
    double equity = AccountInfoDouble(ACCOUNT_EQUITY);
    double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
    double totalProfit = buyTotalProfit + sellTotalProfit;

    // 更新标签文本
    ObjectSetString(0, "Balance", OBJPROP_TEXT, "余额: " + DoubleToString(balance, 2));
    ObjectSetString(0, "Equity", OBJPROP_TEXT, "净值: " + DoubleToString(equity, 2));
    ObjectSetString(0, "FreeMargin", OBJPROP_TEXT, "可用保证金: " + DoubleToString(freeMargin, 2));

    if (buyTotalLots > 0)
    {
        int profitColor = (buyTotalProfit > 0) ? clrLime : clrRed;
        ObjectSetString(0, "ProfitB", OBJPROP_TEXT, "买入盈亏: " + DoubleToString(buyTotalProfit, 2) + " 手数: " + DoubleToString(buyTotalLots, 2));
        ObjectSetInteger(0, "ProfitB", OBJPROP_COLOR, profitColor);
    }
    else
    {
        ObjectSetString(0, "ProfitB", OBJPROP_TEXT, "");
    }

    if (sellTotalLots > 0)
    {
        int profitColor = (sellTotalProfit > 0) ? clrLime : clrRed;
        ObjectSetString(0, "ProfitS", OBJPROP_TEXT, "卖出盈亏: " + DoubleToString(sellTotalProfit, 2) + " 手数: " + DoubleToString(sellTotalLots, 2));
        ObjectSetInteger(0, "ProfitS", OBJPROP_COLOR, profitColor);
    }
    else
    {
        ObjectSetString(0, "ProfitS", OBJPROP_TEXT, "");
    }

    if (sellTotalLots + buyTotalLots > 0)
    {
        int profitColor = (totalProfit >= 0) ? clrLime : clrRed;
        ObjectSetString(0, "Profit", OBJPROP_TEXT, "总盈亏: " + DoubleToString(totalProfit, 2));
        ObjectSetInteger(0, "Profit", OBJPROP_COLOR, profitColor);
    }
    else
    {
        ObjectSetString(0, "Profit", OBJPROP_TEXT, "");
    }
}

//+------------------------------------------------------------------+
//| 获取动态止损价格                                                    |
//+------------------------------------------------------------------+
double GetDynamicStopLoss(int direction, double currentPrice, double stopLevelPoints)
{
    double stopPrice = 0;
    datetime currentTime = TimeCurrent();

    // direction: 1 为买入, -1 为卖出
    if (direction > 0) // 买入止损
    {
        // 搜索最近的低点作为止损
        for (int i = 1; i < MaxBars; i++)
        {
            double lowPrice = iLow(_Symbol, TF_Trailing, i);
            if (lowPrice == 0)
                continue;

            // 计算潜在的止损价格
            stopPrice = NormalizeDouble(lowPrice - delta * _Point, _Digits);

            // 买单的止损价要比当前价格低于基础止损点，挂单等价格回调后触发
            if(stopPrice < currentPrice-stopLevelPoints*_Point)
            {
                // 创建可视化标记
                CreateStopLossMarker("FIND Buy", iTime(_Symbol, TF_Trailing, i), stopPrice, 159, clrWhite);
                if(currentPrice>buyAveragePrice){ //当市场价开始大于当前价可以盈利时，绘制买单止盈的价格
                    CreateStopLossMarker("STOP Buy", currentTime + PeriodSeconds(), stopPrice, 6, clrRed);
                }

                // 创建最小止损距离标记
                if (stopLevelPoints > 0)
                {
                    CreateStopLossMarker("STOPLEVEL-",
                                         currentTime + PeriodSeconds(),
                                         currentPrice - stopLevelPoints,
                                         4,
                                         clrRed);
                }
                break;
            }
            stopPrice = 0;
        }
        // Print("计算的买入止损价格: ", stopPrice);
    }
    else if (direction < 0) // 卖出止损
    {
        // 搜索最近的高点作为止损
        for (int i = 1; i < MaxBars; i++)
        {
            double highPrice = iHigh(_Symbol, TF_Trailing, i);
            if (highPrice == 0)
                continue;

            // 计算潜在的止损价格
            stopPrice = NormalizeDouble(highPrice + delta * _Point, _Digits);

            // 检查是否满足最小止损距离要求 卖单止损价要高于当前价格+基础止损点，保证单据可以挂出去
            if (stopPrice>currentPrice + stopLevelPoints*_Point)
            {
                // 创建可视化标记
                CreateStopLossMarker("FIND Sell", iTime(_Symbol, TF_Trailing, i), stopPrice, 159, clrWhite);
                if(currentPrice<sellAveragePrice){
                    CreateStopLossMarker("STOP Sell", currentTime + PeriodSeconds(), stopPrice, 6, clrBlue);    
                }

                // 创建最小止损距离标记
                if (stopLevelPoints > 0)
                {
                    CreateStopLossMarker("STOPLEVEL+",
                                         currentTime + PeriodSeconds(),
                                         currentPrice + stopLevelPoints,
                                         4,
                                         clrBlue);
                }
                break;
            }
            stopPrice = 0;
        }

        // Print("计算的卖出止损价格: ", stopPrice);
    }

    return stopPrice;
}

//+------------------------------------------------------------------+
//| 创建止损标记                                                       |
//+------------------------------------------------------------------+
void CreateStopLossMarker(string name, datetime time, double price, int arrowCode, color clr)
{
    ObjectDelete(0, name);
    ObjectCreate(0, name, OBJ_ARROW, 0, time, price);
    ObjectSetInteger(0, name, OBJPROP_ARROWCODE, arrowCode);
    ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
}

//+------------------------------------------------------------------+
//| 平仓函数                                                           |
//+------------------------------------------------------------------+
bool CloseAllPositions(int direction = 0, string batchId = "") // 0: 全部平仓, 1: 只平买单, -1: 只平卖单
{
    bool result = true;
    int retryCount = 0;

    // 最多尝试10次平仓
    while (retryCount < 10)
    {
        bool needMoreAttempts = false;

        // 遍历所有持仓
        for (int i = PositionsTotal() - 1; i >= 0; i--)
        {
            if (PositionSelectByTicket(PositionGetTicket(i)))
            {
                // 检查是否是本EA的订单
                if (PositionGetString(POSITION_SYMBOL) == Symbol() &&
                    PositionGetInteger(POSITION_MAGIC) == MagicNumber)
                {
                    ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
                    ulong ticket = PositionGetTicket(i);
                    double volume = PositionGetDouble(POSITION_VOLUME);

                    // 根据方向参数决定是否平仓
                    bool shouldClose = false;
                    if (direction == 0)
                        shouldClose = true;
                    else if (direction > 0 && posType == POSITION_TYPE_BUY)
                        shouldClose = true;
                    else if (direction < 0 && posType == POSITION_TYPE_SELL)
                        shouldClose = true;

                    if (shouldClose)
                    {
                        bool closeResult = trade.PositionClose(ticket);
                        if (closeResult)
                        {
                            PrintFormat("批次 #%s 订单 #%d 平仓成功, 盈亏: %.2f",
                                        batchId,
                                        ticket,
                                        PositionGetDouble(POSITION_PROFIT));
                        }
                        else
                        {
                            int errorCode = GetLastError();
                            if (errorCode == TRADE_RETCODE_REJECT)
                            {
                                Sleep(2000); // 交易繁忙时等待
                                needMoreAttempts = true;
                                continue;
                            }
                            else if (errorCode == TRADE_RETCODE_NO_CHANGES)
                            {
                                needMoreAttempts = true;
                                continue;
                            }
                            else
                            {
                                PrintFormat("批次 #%s 订单 #%d 平仓失败, 错误代码: %d", batchId, ticket, errorCode);
                                result = false;
                            }
                        }
                    }
                }
            }
        }

        // 检查是否还有未平仓的订单
        int remainingOrders = 0;
        for (int i = PositionsTotal() - 1; i >= 0; i--)
        {
            if (PositionSelectByTicket(PositionGetTicket(i)))
            {
                if (PositionGetString(POSITION_SYMBOL) == Symbol() &&
                    PositionGetInteger(POSITION_MAGIC) == MagicNumber)
                {
                    ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

                    if (direction == 0)
                        remainingOrders++;
                    else if (direction > 0 && posType == POSITION_TYPE_BUY)
                        remainingOrders++;
                    else if (direction < 0 && posType == POSITION_TYPE_SELL)
                        remainingOrders++;
                }
            }
        }

        // 如果没有剩余订单或不需要更多尝试，退出循环
        if (remainingOrders == 0 || !needMoreAttempts)
            break;

        retryCount++;
        Sleep(1000);
    }

    // 如果重试次数过多，发出警告
    if (retryCount >= 10)
    {
        int remainingCount = 0;
        for (int i = PositionsTotal() - 1; i >= 0; i--)
        {
            if (PositionSelectByTicket(PositionGetTicket(i)))
            {
                if (PositionGetString(POSITION_SYMBOL) == Symbol() &&
                    PositionGetInteger(POSITION_MAGIC) == MagicNumber)
                {
                    remainingCount++;
                }
            }
        }
        if (remainingCount > 0)
        {
            PrintFormat("警告: %s 还有 %d 个订单未能平仓", Symbol(), remainingCount);
            result = false;
        }
    }

    return result;
}

//+------------------------------------------------------------------+
//| 删除挂单函数                                                       |
//+------------------------------------------------------------------+
bool DeletePendingOrders(int direction = 0) // 0: 删除所有, 1: 只删买单, -1: 只删卖单
{
    bool result = true;

    for (int i = OrdersTotal() - 1; i >= 0; i--)
    {
        ulong ticket = OrderGetTicket(i); // 获取订单ticket
        if (ticket > 0)                   // 如果成功获取ticke
        {
            if (OrderSelect(ticket))
            {
                // 检查是否是本EA的订单
                if (OrderGetString(ORDER_SYMBOL) == Symbol() &&
                    OrderGetInteger(ORDER_MAGIC) == MagicNumber)
                {
                    ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
                    ulong ticket = OrderGetTicket(i);

                    // 根据方向参数决定是否删除
                    bool shouldDelete = false;
                    if (direction == 0)
                        shouldDelete = true;
                    else if (direction > 0 && (orderType == ORDER_TYPE_BUY_LIMIT || orderType == ORDER_TYPE_BUY_STOP))
                        shouldDelete = true;
                    else if (direction < 0 && (orderType == ORDER_TYPE_SELL_LIMIT || orderType == ORDER_TYPE_SELL_STOP))
                        shouldDelete = true;

                    if (shouldDelete)
                    {
                        if (!trade.OrderDelete(ticket))
                        {
                            PrintFormat("删除挂单 #%d 失败, 错误代码: %d", ticket, GetLastError());
                            result = false;
                        }
                    }
                }
            }
        }
    }

    return result;
}

//+------------------------------------------------------------------+
//| 市场状态分析相关函数                                              |
//+------------------------------------------------------------------+

// 更新市场状态
// void UpdateMarketCondition() { ... }
// double GetCurrentVolatility() { ... }
// double GetAverageVolatility() { ... }
// void DrawMarketStateTransition() { ... }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                   |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // 记录EA停止日志
    if(g_logger.IsInitialized()) {
        g_logger.Log(LOG_LEVEL_INFO, "=== EA停止运行 ===", EnableConsoleLog);
        g_logger.Log(LOG_LEVEL_INFO, "停止原因: " + IntegerToString(reason), EnableConsoleLog);
        g_logger.Log(LOG_LEVEL_INFO, "运行时间: " + TimeToString(TimeCurrent() - g_startTime), EnableConsoleLog);
    }
    
    if(g_panel) { g_panel.Destroy(); delete g_panel; g_panel = NULL; }
    EventKillTimer();

    // 保存批次数据到CSV
    int fileHandle = FileOpen("BatchReport.csv", FILE_WRITE | FILE_CSV | FILE_ANSI);
    if (fileHandle != INVALID_HANDLE)
    {
        FileWrite(fileHandle, "BatchID,Type,StartTime,EndTime,TotalLots,MaxMultiplier,MaxDrawdown,FinalProfit");

        for (int i = 0; i < buyBatches.Total(); i++)
        {
            CBatchInfo *batch = buyBatches.At(i);
            FileWrite(fileHandle,
                      batch.batchId,
                      "BUY",
                      TimeToString(batch.startTime),
                      TimeToString(batch.endTime),
                      DoubleToString(batch.totalLots, 2),
                      DoubleToString(batch.maxMultiplier, 2),
                      DoubleToString(batch.maxDrawdown, 2),
                      DoubleToString(batch.finalProfit, 2));
        }

        for (int i = 0; i < sellBatches.Total(); i++)
        {
            CBatchInfo *batch = sellBatches.At(i);
            FileWrite(fileHandle,
                      batch.batchId,
                      "SELL",
                      TimeToString(batch.startTime),
                      TimeToString(batch.endTime),
                      DoubleToString(batch.totalLots, 2),
                      DoubleToString(batch.maxMultiplier, 2),
                      DoubleToString(batch.maxDrawdown, 2),
                      DoubleToString(batch.finalProfit, 2));
        }

        FileClose(fileHandle);
        
        if(g_logger.IsInitialized()) {
            g_logger.Log(LOG_LEVEL_INFO, "批次报告已保存到 BatchReport.csv", EnableConsoleLog);
        }
    }

    // 清理内存
    if (buyBatches != NULL)
    {
        buyBatches.Clear();
        delete buyBatches;
    }
    if (sellBatches != NULL)
    {
        sellBatches.Clear();
        delete sellBatches;
    }

    // 清理订单关系数组
    if (orderRelations != NULL)
    {
        orderRelations.Clear();
        delete orderRelations;
    }

    // 删除图形对象
    ObjectDelete(0, "TrendInfo");     // 删除趋势信息标签
    ObjectsDeleteAll(0);
    
    if(g_bbHandle != INVALID_HANDLE)
    {
        IndicatorRelease(g_bbHandle);
    }
    if(g_ma20Handle != INVALID_HANDLE)
    {
        ChartIndicatorDelete(0, 0, g_ma20Handle);
        IndicatorRelease(g_ma20Handle);
    }
    /* 暂时注释掉50均线
    if(g_ma50Handle != INVALID_HANDLE)
    {
        ChartIndicatorDelete(0, 0, g_ma50Handle);
        IndicatorRelease(g_ma50Handle);
    }
    */
    
    // 关闭日志系统
    if(g_logger.IsInitialized()) {
        g_logger.Log(LOG_LEVEL_INFO, "=== EA清理完成 ===", EnableConsoleLog);
        g_logger.Close();
    }
}


// 修改FindOrder方法，增加对原始订单的查找
CMartingaleOrderInfo *FindOrder(ulong ticket, ulong positionId = 0)
{
    // 首先尝试直接通过ticket查找
    for (int i = 0; i < buyBatches.Total(); i++)
    {
        CBatchInfo *batch = buyBatches.At(i);
        for (int j = 0; j < batch.orders.Total(); j++)
        {
            CMartingaleOrderInfo *order = batch.orders.At(j);
            if (order.orderTicket == ticket)
                return order;
        }
    }
    for (int i = 0; i < sellBatches.Total(); i++)
    {
        CBatchInfo *batch = sellBatches.At(i);
        for (int j = 0; j < batch.orders.Total(); j++)
        {
            CMartingaleOrderInfo *order = batch.orders.At(j);
            if (order.orderTicket == ticket)
                return order;
        }
    }

    // 如果找不到，且positionId不为0，尝试通过positionId查找原始订单
    if (positionId != 0)
    {
        for (int i = 0; i < buyBatches.Total(); i++)
        {
            CBatchInfo *batch = buyBatches.At(i);
            for (int j = 0; j < batch.orders.Total(); j++)
            {
                CMartingaleOrderInfo *order = batch.orders.At(j);
                if (order.orderTicket == positionId)
                    return order;
            }
        }
        for (int i = 0; i < sellBatches.Total(); i++)
        {
            CBatchInfo *batch = sellBatches.At(i);
            for (int j = 0; j < batch.orders.Total(); j++)
            {
                CMartingaleOrderInfo *order = batch.orders.At(j);
                if (order.orderTicket == positionId)
                    return order;
            }
        }
    }

    return NULL;
}

// 简化OnTradeTransaction中的订单查找逻辑
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
{
    static string currentBuyBatchId = "";
    static string currentSellBatchId = "";

    // 处理订单成交事件
    if (trans.type == TRADE_TRANSACTION_DEAL_ADD)
    {
        // 获取成交信息
        ulong dealTicket = trans.deal;
        if (HistoryDealSelect(dealTicket))
        {
            ENUM_DEAL_ENTRY dealEntry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(dealTicket, DEAL_ENTRY);
            ENUM_DEAL_TYPE dealType = (ENUM_DEAL_TYPE)HistoryDealGetInteger(dealTicket, DEAL_TYPE);
            ulong orderTicket = HistoryDealGetInteger(dealTicket, DEAL_ORDER);
            ulong positionId = HistoryDealGetInteger(dealTicket, DEAL_POSITION_ID);
            
            // 记录成交日志
            // LogInfo(StringFormat("成交 #%d: 类型=%s, 入场=%s, 订单=%d, 持仓ID=%d", 
            //     dealTicket,
            //     EnumToString(dealType),
            //     EnumToString(dealEntry),
            //     orderTicket,
            //     positionId));

            // 如果是入场成交
            if (dealEntry == DEAL_ENTRY_IN)
            {
                // 检查是否达到最大订单数量
                if (dealType == DEAL_TYPE_BUY && buyOrderCount >= MaxOrderCount)
                {
                    maxBuyTime = TimeCurrent();
                    maxBuyDrawdown = 0;
                    // Print("达到最大买单数量，记录时间: ", TimeToString(maxBuyTime));
                }
                else if (dealType == DEAL_TYPE_SELL && sellOrderCount >= MaxOrderCount)
                {
                    maxSellTime = TimeCurrent();
                    maxSellDrawdown = 0;
                    // Print("达到最大卖单数量，记录时间: ", TimeToString(maxSellTime));
                }

                // 添加订单数量提醒
                if (dealType == DEAL_TYPE_BUY && (buyOrderCount == 6 || buyOrderCount == 7))
                {
                    string alertMessage = StringFormat("%s - 买单数量达到 %d 单，请注意盯盘！", _Symbol, buyOrderCount);
                    LogWarn(alertMessage);
                    Alert(alertMessage);
                    PlaySound("alert.wav");
                }
                else if (dealType == DEAL_TYPE_SELL && (sellOrderCount == 6 || sellOrderCount == 7))
                {
                    string alertMessage = StringFormat("%s - 卖单数量达到 %d 单，请注意盯盘！", _Symbol, sellOrderCount);
                    LogWarn(alertMessage);
                    Alert(alertMessage);
                    PlaySound("alert.wav");
                }

                CMartingaleOrderInfo *order = new CMartingaleOrderInfo();
                order.orderTicket = orderTicket;
                order.orderOpenTime = TimeCurrent();
                order.orderLots = HistoryDealGetDouble(dealTicket, DEAL_VOLUME);
                order.orderOpenPrice = HistoryDealGetDouble(dealTicket, DEAL_PRICE);
                order.orderType = (ENUM_ORDER_TYPE)HistoryDealGetInteger(dealTicket, DEAL_TYPE);
                
                // 在实际成交时更新lastBuyLot和lastSellLot
                if(order.orderType == ORDER_TYPE_BUY) {
                    lastBuyLot = order.orderLots;
                    PrintFormat("[成交更新] 买入订单 #%d 成交，更新lastBuyLot: %.2f", orderTicket, lastBuyLot);
                } else if(order.orderType == ORDER_TYPE_SELL) {
                    lastSellLot = order.orderLots;
                    PrintFormat("[成交更新] 卖出订单 #%d 成交，更新lastSellLot: %.2f", orderTicket, lastSellLot);
                }

                // 判断批次归属
                if (order.orderType == ORDER_TYPE_BUY)
                {
                    if (currentBuyBatchId == "" || isNewBuyBatch)
                    {
                        currentBuyBatchId = "B" + IntegerToString(buyBatchCounter++);
                    }
                    order.orderBatchId = currentBuyBatchId;
                }
                else if (order.orderType == ORDER_TYPE_SELL)
                {
                    if (currentSellBatchId == "" || isNewSellBatch)
                    {
                        currentSellBatchId = "S" + IntegerToString(sellBatchCounter++);
                    }
                    order.orderBatchId = currentSellBatchId;
                }

                CBatchInfo *batch = FindBatch(order.orderBatchId);
                
                // 如果批次不存在，创建新批次
                if (batch == NULL)
                {
                    batch = new CBatchInfo();
                    batch.batchId = order.orderBatchId;
                    batch.startTime = TimeCurrent();
                    batch.batchType = (order.orderType == ORDER_TYPE_BUY) ? POSITION_TYPE_BUY : POSITION_TYPE_SELL;
                    
                    // 添加到对应的批次数组
                    if (batch.batchType == POSITION_TYPE_BUY)
                    {
                        buyBatches.Add(batch);
                        // 重置最大回撤
                        buyMaxDrawdown = 0;
                        buyCurrentProfit = 0;
                        isNewBuyBatch = false;
                    }
                    else
                    {
                        sellBatches.Add(batch);
                        // 重置最大回撤
                        sellMaxDrawdown = 0;
                        sellCurrentProfit = 0;
                        isNewSellBatch = false;
                    }
                    
                    // 记录批次开始日志
                    PrintFormat("%s批次 %s 开始, 开始时间: %s, 当前手数: %.2f", 
                        batch.batchType == POSITION_TYPE_BUY ? "买入" : "卖出",
                        batch.batchId, 
                        TimeToString(batch.startTime),
                        order.orderLots);
                }

                // 添加订单到批次
                batch.orders.Add(order);
            }
            // 如果是出场成交（包括止盈止损和直接平仓）
            else if (dealEntry == DEAL_ENTRY_OUT)
            {
                // 使用修改后的FindOrder方法查找订单
                CMartingaleOrderInfo *order = FindOrder(orderTicket, positionId);
                
                if (order != NULL)
                {
                    order.orderCloseTime = TimeCurrent();
                    order.orderClosePrice = HistoryDealGetDouble(dealTicket, DEAL_PRICE);

                    // 更新当前收益
                    if (order.orderType == ORDER_TYPE_BUY)
                    {
                       buyCurrentProfit += IsBitcoin() ? (order.orderClosePrice - order.orderOpenPrice) * (order.orderLots/minLot) / 100 : (order.orderClosePrice - order.orderOpenPrice) * (order.orderLots/minLot);
                    }
                    else
                    {
                       sellCurrentProfit += IsBitcoin() ? (order.orderOpenPrice - order.orderClosePrice) * (order.orderLots/minLot) / 100 :  (order.orderOpenPrice - order.orderClosePrice) * (order.orderLots/minLot);
                    }

                    CBatchInfo *batch = FindBatch(order.orderBatchId);
                    if (batch != NULL)
                    {
                        // 检查是否所有订单都已平仓
                        bool allOrdersClosed = true;
                        double totalBatchLots = 0;
                        for (int i = 0; i < batch.orders.Total(); i++)
                        {
                            CMartingaleOrderInfo *ord = batch.orders.At(i);
                            if (ord.orderCloseTime == 0)
                            {
                                allOrdersClosed = false;
                            }
                            totalBatchLots += ord.orderLots;
                        }

                        // 如果所有订单都已平仓,结束批次
                        if (allOrdersClosed)
                        {
                            batch.endTime = TimeCurrent();
                            datetime duration = batch.endTime - batch.startTime;
                            
                            if (batch.batchType == POSITION_TYPE_BUY)
                            {
                                PrintFormat("买入批次 %s 结束 | 开始时间: %s | 结束时间: %s | 耗时: %s | 最大回撤: %.2f | 最终收益: %.2f | 总手数: %.2f | 订单数: %d",
                                    batch.batchId,
                                    TimeToString(batch.startTime),
                                    TimeToString(batch.endTime),
                                    TimeToString(duration, TIME_MINUTES),
                                    buyMaxDrawdown,
                                    buyCurrentProfit,
                                    totalBatchLots,
                                    batch.orders.Total());
                                isNewBuyBatch = true;
                                currentBuyBatchId = "";
                                // 重置最大订单时间
                                maxBuyTime = 0;
                                maxBuyDrawdown = 0;
                                // 重置lastBuyLot，为新批次准备
                                lastBuyLot = 0;
                                PrintFormat("[批次重置] 买入批次结束，重置lastBuyLot为0");
                            }
                            else
                            {
                                PrintFormat("卖出批次 %s 结束 | 开始时间: %s | 结束时间: %s | 耗时: %s | 最大回撤: %.2f | 最终收益: %.2f | 总手数: %.2f | 订单数: %d",
                                    batch.batchId,
                                    TimeToString(batch.startTime),
                                    TimeToString(batch.endTime),
                                    TimeToString(duration, TIME_MINUTES),
                                    sellMaxDrawdown,
                                    sellCurrentProfit,
                                    totalBatchLots,
                                    batch.orders.Total());
                                isNewSellBatch = true;
                                currentSellBatchId = "";
                                // 重置最大订单时间
                                maxSellTime = 0;
                                maxSellDrawdown = 0;
                                // 重置lastSellLot，为新批次准备
                                lastSellLot = 0;
                                PrintFormat("[批次重置] 卖出批次结束，重置lastSellLot为0");
                            }
                        }
                    }
                    else
                    {
                        // Print("找不到批次", order.orderBatchId);
                    }
                }
                else
                {
                    // Print("找不到订单", orderTicket, " 持仓ID", positionId);
                }
            }
        }
    }
}

CBatchInfo *FindBatch(string batchId)
{
    for (int i = 0; i < buyBatches.Total(); i++)
    {
        CBatchInfo *batch = buyBatches.At(i);
        if (batch.batchId == batchId)
            return batch;
    }
    for (int i = 0; i < sellBatches.Total(); i++)
    {
        CBatchInfo *batch = sellBatches.At(i);
        if (batch.batchId == batchId)
            return batch;
    }
    return NULL;
}

void CalculateOrderDrawdown(CMartingaleOrderInfo *order)
{
    double maxDD = 0;
    double currentDD = 0;

    if (order.orderType == ORDER_TYPE_BUY)
    {
        for (int i = 0; i < buyBatches.Total(); i++)
        {
            CBatchInfo *batch = buyBatches.At(i);
            if (batch.batchId == order.orderBatchId)
            {
                for (int j = 0; j < batch.orders.Total(); j++)
                {
                    CMartingaleOrderInfo *ord = batch.orders.At(j);
                    if (ord.orderTicket == order.orderTicket)
                    {
                        currentDD = ord.orderClosePrice - ord.orderOpenPrice;
                        maxDD = MathMin(maxDD, currentDD);
                    }
                }
            }
        }
    }
    else if (order.orderType == ORDER_TYPE_SELL)
    {
        for (int i = 0; i < sellBatches.Total(); i++)
        {
            CBatchInfo *batch = sellBatches.At(i);
            if (batch.batchId == order.orderBatchId)
            {
                for (int j = 0; j < batch.orders.Total(); j++)
                {
                    CMartingaleOrderInfo *ord = batch.orders.At(j);
                    if (ord.orderTicket == order.orderTicket)
                    {
                        currentDD = ord.orderOpenPrice - ord.orderClosePrice;
                        maxDD = MathMin(maxDD, currentDD);
                    }
                }
            }
        }
    }

    order.orderMaxDrawdown = maxDD;
}

void UpdateBatchStats(CBatchInfo *batch)
{
    double totalLots = 0;
    double maxLots = 0;
    double maxDD = 0;
    double totalProfit = 0;

    for (int i = 0; i < batch.orders.Total(); i++)
    {
        CMartingaleOrderInfo *order = batch.orders.At(i);
        totalLots += order.orderLots;
        maxLots = MathMax(maxLots, order.orderLots);
        maxDD = MathMin(maxDD, order.orderMaxDrawdown);

        if (order.orderCloseTime != 0)
        {
            if (order.orderType == ORDER_TYPE_BUY)
            {
                totalProfit += (order.orderClosePrice - order.orderOpenPrice) * order.orderLots;
            }
            else
            {
                totalProfit += (order.orderOpenPrice - order.orderClosePrice) * order.orderLots;
            }
        }
    }

    batch.totalLots = totalLots;
    batch.maxMultiplier = maxLots / g_InitialLot;
    batch.maxDrawdown = maxDD;
    batch.finalProfit = totalProfit;
}

//+------------------------------------------------------------------+
//| 更新最大回撤                                                       |
//+------------------------------------------------------------------+
void UpdateMaxDrawdown()
{
    // 更新买单最大回撤
    if (buyTotalProfit < buyMaxDrawdown)
    {
        buyMaxDrawdown = buyTotalProfit;
    }

    // 更新卖单最大回撤
    if (sellTotalProfit < sellMaxDrawdown)
    {
        sellMaxDrawdown = sellTotalProfit;
    }
}

// 添加函数来查找原始订单号
ulong FindOriginalTicket(ulong currentTicket)
{
    for(int i = 0; i < orderRelations.Total(); i++)
    {
        COrderRelation *relation = orderRelations.At(i);
        if(relation.currentTicket == currentTicket)
            return relation.originalTicket;
    }
    return currentTicket;  // 如果没有找到关系，返回当前订单号
}

// 添加函数来更新订单关系
void UpdateOrderRelation(ulong originalTicket, ulong currentTicket)
{
    // 检查是否已存在关系
    for(int i = 0; i < orderRelations.Total(); i++)
    {
        COrderRelation *relation = orderRelations.At(i);
        if(relation.currentTicket == currentTicket)
        {
            relation.originalTicket = originalTicket;
            return;
        }
    }
    
    // 创建新的关系
    COrderRelation *relation = new COrderRelation();
    relation.originalTicket = originalTicket;
    relation.currentTicket = currentTicket;
    orderRelations.Add(relation);
}

// 添加函数来检查是否是比特币
bool IsBitcoin()
{
    return StringFind(_Symbol, "BTC") >= 0;
}

//+------------------------------------------------------------------+
//| 处理时间限制平仓                                                   |
//+------------------------------------------------------------------+
void HandleTimeLimitClose()
{
    // 如果没有任何批次达到最大订单数，直接返回
    if (maxBuyTime == 0 && maxSellTime == 0)
        return;

    datetime now = TimeCurrent();

    // 遍历所有持仓
    for (int i = PositionsTotal() - 1; i >= 0; i--)
    {
        if (PositionSelectByTicket(PositionGetTicket(i)))
        {
            if (PositionGetString(POSITION_SYMBOL) == Symbol() &&
                PositionGetInteger(POSITION_MAGIC) == MagicNumber)
            {
                ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

                // 检查是否达到最大订单数量
                if (posType == POSITION_TYPE_BUY && buyOrderCount >= MaxOrderCount && maxBuyTime > 0)
                {
                    datetime timeDiff = now - maxBuyTime;
                    int minutesPassed = (int)(timeDiff / 60);

                    // 0-5分钟尝试保本
                    if (minutesPassed <= MaxTimeLimit)
                    {
                        if (buyTotalProfit > 0)
                        {
                            Alert("警告：买单保本平仓触发！\n当前利润: ", buyTotalProfit);
                            CloseAllPositions(1, "TSL-B" + IntegerToString(buyBatchCounter));
                            // Print("买单保本平仓，当前利润: ", buyTotalProfit);
                        }
                    }
                    // 5分钟后直接平仓
                    else
                    {
                        Alert("警告：买单超时平仓触发！\n持仓时间: ", minutesPassed, "分钟");
                        CloseAllPositions(1, "TSL-B" + IntegerToString(buyBatchCounter));
                        // Print("买单超时平仓，持仓时间: ", minutesPassed, "分钟");
                    }
                }
                else if (posType == POSITION_TYPE_SELL && sellOrderCount >= MaxOrderCount && maxSellTime > 0)
                {
                    datetime timeDiff = now - maxSellTime;
                    int minutesPassed = (int)(timeDiff / 60);

                    // 0-5分钟尝试保本
                    if (minutesPassed <= MaxTimeLimit)
                    {
                        if (sellTotalProfit > 0)
                        {
                            Alert("警告：卖单保本平仓触发！\n当前利润: ", sellTotalProfit);
                            CloseAllPositions(-1, "TSL-S" + IntegerToString(sellBatchCounter));
                            // Print("卖单保本平仓，当前利润: ", sellTotalProfit);
                        }
                    }
                    // 5分钟后直接平仓
                    else
                    {
                        Alert("警告：卖单超时平仓触发！\n持仓时间: ", minutesPassed, "分钟");
                        CloseAllPositions(-1, "TSL-S" + IntegerToString(sellBatchCounter));
                        // Print("卖单超时平仓，持仓时间: ", minutesPassed, "分钟");
                    }
                }
            }
        }
    }
}

// 修改函数来根据输入参数和币种计算最小获利点数
double GetMinProfit()
{
    // 获取ATR指标句柄
    int atrHandle = iATR(_Symbol, TF_Trailing, 14);
    if(atrHandle == INVALID_HANDLE)
    {
        // Print("获取ATR指标失败");
        return 0.0;
    }
    // 获取ATR值
    double atrBuffer[];
    if(CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) < 1)
    {
        // Print("复制ATR数据失败");
        return 0.0;
    }
    double atrValue = atrBuffer[0];
    return TakeProfitATR * atrValue;
}

void OnTimer()
{
    if(g_panel) 
    {
        g_panel.Refresh();
        g_panel.BringToTop();  // 每次更新时都确保面板在最上层
    }
}

// 添加 OnChartEvent 函数
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
    // 不管点哪里，所有事件都传递给面板
    if(g_panel != NULL)
        g_panel.OnEvent(id, lparam, dparam, sparam);
}

// 添加全局变量以记录锁单状态
bool g_isLocked = false;           // 是否处于锁单状态
bool g_isUnlocking = false;        // 是否处于解锁状态
ENUM_POSITION_TYPE g_lockType;     // 锁单类型
double g_lockLots = 0;            // 锁单手数
ulong g_lockTicket = 0;           // 锁单票据
double g_lockProfit = 0;          // 锁单收益

// 趋势可视化相关变量
datetime g_lastTrendUpdate = 0;    // 上次趋势更新时间
datetime g_lastSmartAddLog = 0;    // 上次智能加仓日志时间

// 锁单方法
void LockPosition(ENUM_POSITION_TYPE posType)
{
    if(g_isLocked) return; // 如果已经锁单，直接返回
    
    double lockLots = 0;
    string lockComment = "";
    ENUM_ORDER_TYPE lockOrderType;
    
    // 获取当前持仓总手数
    if(posType == POSITION_TYPE_BUY)
    {
        lockLots = buyTotalLots;
        lockComment = "sell_lock";
        lockOrderType = ORDER_TYPE_SELL;
    }
    else
    {
        lockLots = sellTotalLots;
        lockComment = "buy_lock";
        lockOrderType = ORDER_TYPE_BUY;
    }
    
    if(lockLots <= 0) return; // 如果没有持仓，直接返回
    
    // 删除所有挂单
    DeletePendingOrders();
    
    // 平掉其他方向的持仓
    if(posType == POSITION_TYPE_BUY)
    {
        CloseAllPositions(-1, "Lock-B");
    }
    else
    {
        CloseAllPositions(1, "Lock-S");
    }
    
    // 开锁单
    MqlTick latest_price;
    if(!SymbolInfoTick(_Symbol, latest_price)) return;
    
    double price = (posType == POSITION_TYPE_BUY) ? latest_price.bid : latest_price.ask;
    
    if(trade.PositionOpen(_Symbol, lockOrderType, lockLots, price, 0, 0, lockComment))
    {
        g_isLocked = true;
        g_lockType = posType;
        g_lockLots = lockLots;
        g_lockTicket = trade.ResultOrder();
        g_lockProfit = 0;
        
        // Print("锁单成功 - 类型: ", EnumToString(posType), " 手数: ", lockLots);
    }
    else
    {
        // Print("锁单失败 - 错误代码: ", GetLastError());
    }
}

// 解锁方法
void UnlockPosition()
{
    if(!g_isLocked) return;
    
    // 计算反向单的手数
    double reverseLot = g_InitialLot;
    if(g_lockType == POSITION_TYPE_BUY)
    {
        if(buyOrderCount > 0)
            reverseLot = NormalizeDouble(MathFloor(MathPow(g_MultiplierOnLoss, buyOrderCount)) * g_InitialLot, 2);
    }
    else
    {
        if(sellOrderCount > 0)
            reverseLot = NormalizeDouble(MathFloor(MathPow(g_MultiplierOnLoss, sellOrderCount)) * g_InitialLot, 2);
    }
    
    // 开反向单
    MqlTick latest_price;
    if(!SymbolInfoTick(_Symbol, latest_price)) return;
    
    double price = (g_lockType == POSITION_TYPE_BUY) ? latest_price.bid : latest_price.ask;
    ENUM_ORDER_TYPE reverseType = (g_lockType == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;
    
    if(trade.PositionOpen(_Symbol, reverseType, reverseLot, price, 0, 0, "reverse_before_unlock"))
    {
        // Print("解锁前反向单开仓成功 - 类型: ", EnumToString(reverseType), " 手数: ", reverseLot);
    }
    else
    {
        // Print("解锁前反向单开仓失败 - 错误代码: ", GetLastError());
        return;  // 如果反向单开仓失败，不执行解锁
    }
    
    // 查找锁单
    for(int i = PositionsTotal() - 1; i >= 0; i--)
    {
        if(PositionSelectByTicket(PositionGetTicket(i)))
        {
            string comment = PositionGetString(POSITION_COMMENT);
            if(StringFind(comment, "lock") >= 0)
            {
                if(trade.PositionClose(PositionGetTicket(i)))
                {
                    g_lockProfit = PositionGetDouble(POSITION_PROFIT);
                    // Print("解锁成功 - 收益: ", g_lockProfit);
                    
                    // 设置解锁状态
                    g_isLocked = false;
                    g_isUnlocking = true;
                    
                    // 重置其他锁单相关变量
                    g_lockLots = 0;
                    g_lockTicket = 0;
                    return;
                }
                else
                {
                    // Print("解锁失败 - 错误代码: ", GetLastError());
                }
            }
        }
    }
}

// 添加保本平仓方法
void HandleBreakEven()
{
    if(!g_isUnlocking) return;
    
    double currentProfit = 0;
    
    // 计算当前持仓的收益
    if(g_lockType == POSITION_TYPE_BUY)
    {
        currentProfit = buyTotalProfit;
    }
    else
    {
        currentProfit = sellTotalProfit;
    }

    // 如果总收益大于0，平掉所有持仓
    if(currentProfit + g_lockProfit > 0)
    {
        // Print("保本平仓触发 - 当前收益: ", currentProfit, " 锁单收益: ", g_lockProfit);
        
        // 平掉所有持仓
        if(g_lockType == POSITION_TYPE_BUY)
        {
            CloseAllPositions(1, "BE-B");
        }
        else
        {
            CloseAllPositions(-1, "BE-S");
        }
        
        // 重置所有状态
        g_isUnlocking = false;
        g_isLocked = false;  // 确保锁单状态也被重置
        g_lockType = 0;
        g_lockLots = 0;
        g_lockTicket = 0;
        g_lockProfit = 0;
        
        // Print("保本平仓完成，状态已重置");
    }
}

// 检查是否应该锁单
void CheckLockCondition()
{
    if(g_isLocked || !AllowLockPosition) return;
    
    // 检查买单锁单条件
    if(buyTotalProfit < -1000 || (buyTotalProfit < -500 && CheckBearishPattern()))
    {
        string alertMessage = StringFormat("警告：买单锁单条件触发！\n当前亏损: %.2f", buyTotalProfit);
        Alert(alertMessage);
        PlaySound("alert.wav");  // 播放
        LockPosition(POSITION_TYPE_BUY);
        g_lockStartTime = TimeCurrent();
        return;
    }
    
    // 检查卖单锁单条件
    if(sellTotalProfit < -1000 || (sellTotalProfit < -500 && CheckBullishPattern()))
    {
        string alertMessage = StringFormat("警告：卖单锁单条件触发！\n当前亏损: %.2f", sellTotalProfit);
        Alert(alertMessage);
        PlaySound("alert.wav");  // 播放
        LockPosition(POSITION_TYPE_SELL);
        g_lockStartTime = TimeCurrent();
        return;
    }
}

// 检查阴线模式
bool CheckBearishPattern()
{
    // 检查15分钟连续2根阴线
    bool hasTwoBearish15M = true;
    for(int i = 1; i <= 2; i++)
    {
        double open = iOpen(_Symbol, PERIOD_M15, i);
        double close = iClose(_Symbol, PERIOD_M15, i);
        if(close >= open)
        {
            hasTwoBearish15M = false;
            break;
        }
    }
    
    // 检查5分钟7根K线中5根阴线
    int bearishCount = 0;
    for(int i = 1; i <= 7; i++)
    {
        double open = iOpen(_Symbol, PERIOD_M5, i);
        double close = iClose(_Symbol, PERIOD_M5, i);
        if(close < open)
        {
            bearishCount++;
        }
    }
    
    // Print("hasTwoBearish15M: ", hasTwoBearish15M, " bearishCount: ", bearishCount);
    return hasTwoBearish15M || bearishCount >= 5;
}

// 检查阳线模式
bool CheckBullishPattern()
{
    // 检查15分钟连续2根阳线
    bool hasTwoBullish15M = true;
    for(int i = 1; i <= 2; i++)
    {
        double open = iOpen(_Symbol, PERIOD_M15, i);
        double close = iClose(_Symbol, PERIOD_M15, i);
        if(close <= open)
        {
            hasTwoBullish15M = false;
            break;
        }
    }
    
    // 检查5分钟7根K线中5根阳线
    int bullishCount = 0;
    for(int i = 1; i <= 7; i++)
    {
        double open = iOpen(_Symbol, PERIOD_M5, i);
        double close = iClose(_Symbol, PERIOD_M5, i);
        if(close > open)
        {
            bullishCount++;
        }
    }
    
    // Print("hasTwoBullish15M: ", hasTwoBullish15M, " bullishCount: ", bullishCount);
    return hasTwoBullish15M || bullishCount >= 5;
}

// 检查是否应该解锁
void CheckUnlockCondition()
{
    if(!g_isLocked || g_isUnlocking) return;
    
    datetime currentTime = TimeCurrent();
    // Print("当前时间: ", currentTime, " 锁定时间: ", g_lockStartTime, " 时间差: ", currentTime - g_lockStartTime);
    if(currentTime - g_lockStartTime < 3600) return; // 未到1小时
    
    // 获取布林带数据
    double bbUpper[1], bbMiddle[1], bbLower[1];
    if(CopyBuffer(g_bbHandle, 1, 0, 1, bbUpper) <= 0) return;
    if(CopyBuffer(g_bbHandle, 0, 0, 1, bbMiddle) <= 0) return;
    if(CopyBuffer(g_bbHandle, 2, 0, 1, bbLower) <= 0) return;
    
    // 计算布林带宽度变化率
    // double widthChange = CalculateBBWidthChange();
    // bool isExpanding = MathAbs(widthChange) > BB_WidthThreshold;
    // Print("布林带宽度变化率: ", widthChange, " 是否开口: ", isExpanding);
    bool isExpanding=false;
    
    // 获取当前价格
    // MqlTick latest_price;
    // if(!SymbolInfoTick(_Symbol, latest_price)) return;
    
    double marketAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    double marketBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    
    // 检查当前K线
    double currentOpen = iOpen(_Symbol, PERIOD_CURRENT, 0);
    bool isBullish = marketAsk > currentOpen;
    bool isBearish = marketBid < currentOpen;

    // 检查解锁条件
    if(g_lockType == POSITION_TYPE_BUY)
    {
        if(!isExpanding && isBullish && marketBid < bbLower[0] && currentOpen < bbLower[0])
        {
            // Print("买单解锁条件触发 - 价格位于布林带下轨之下，当前K线为阳线，布林带未开口");
            UnlockPosition();
        }
    }
    else if(g_lockType == POSITION_TYPE_SELL)
    {
        if(!isExpanding && isBearish && marketAsk > bbUpper[0] && currentOpen > bbUpper[0])
        {
            // Print("卖单解锁条件触发 - 价格位于布林带上轨之上，当前K线为阴线，布林带未开口");
            UnlockPosition();
        }
    }
}

// 计算布林带宽度变化率
double CalculateBBWidthChange()
{
    double bbUpper[], bbLower[];
    ArraySetAsSeries(bbUpper, true);
    ArraySetAsSeries(bbLower, true);
    
    if(CopyBuffer(g_bbHandle, 1, 0, 2, bbUpper) <= 0) return 0;
    if(CopyBuffer(g_bbHandle, 2, 0, 2, bbLower) <= 0) return 0;
    
    double currentWidth = bbUpper[0] - bbLower[0];
    double previousWidth = bbUpper[1] - bbLower[1];
    
    if(previousWidth == 0) return 0;
    
    return (currentWidth - previousWidth) / previousWidth;
}

// 添加均线判断函数
bool IsPriceBelowMA()
{
    double ma20[];
    ArraySetAsSeries(ma20, true);
    
    // 获取20周期均线数据
    if(CopyBuffer(g_ma20Handle, 0, 0, 1, ma20) <= 0) 
    {
        return false;
    }
    
    // 获取当前价格
    MqlTick latest_price;
    if(!SymbolInfoTick(_Symbol, latest_price)) 
    {
        return false;
    }
    
    // 使用买入价（bid）作为当前价格
    double currentPrice = latest_price.bid;
    
     // 当前价格低于20均线
    return (currentPrice < ma20[0]);
}

bool IsPriceAboveMA()
{
    double ma20[];
    ArraySetAsSeries(ma20, true);
    
    // 获取20周期均线数据
    if(CopyBuffer(g_ma20Handle, 0, 0, 1, ma20) <= 0) 
    {
        return false;
    }
    
    // 获取当前价格
    MqlTick latest_price;
    if(!SymbolInfoTick(_Symbol, latest_price)) 
    {
        return false;
    }
    
    // 使用卖出价（ask）作为当前价格
    double currentPrice = latest_price.ask;
    
    // 当前价格高于20均线
    return (currentPrice > ma20[0]);
}

// 添加挂单距离管理函数
double GetOrderDistance()
{
    // 获取ATR值
    int atrHandle = iATR(_Symbol, TF_Trailing, 14);
    double atrBuffer[];
    if(CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) < 1)
    {
        // Print("获取ATR失败");
        return 0;
    }
    
    double atrValue = atrBuffer[0];
    if(atrValue < 0.5 && StringFind(_Symbol, "GBPUSDm") < 0 && StringFind(_Symbol, "USDJPAm") < 0)
    {
        atrValue = 0.8;
    }
    
    // 计算实际挂单距离
    double distance = OrderDistanceATR * atrValue;
    
    // 确保距离不小于最小挂单距离
    double minDistance = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * _Point;
    return MathMax(distance, minDistance);
}

// 检查挂单价格是否有效
bool IsValidOrderPrice(double price, double currentPrice, ENUM_ORDER_TYPE orderType)
{
    double distance = GetOrderDistance();
    
    // 检查是否满足最小挂单距离
    if(orderType == ORDER_TYPE_BUY_STOP)
    {
        return (price - currentPrice) >= distance;
    }
    else if(orderType == ORDER_TYPE_SELL_STOP)
    {
        return (currentPrice - price) >= distance;
    }
    
    return false;
}

// 计算加仓价格
double CalculateAddOrderPrice(double currentPrice, double basePrice, ENUM_ORDER_TYPE orderType)
{
    double distance = GetOrderDistance();
    
    if(orderType == ORDER_TYPE_BUY_STOP)
    {
        return NormalizeDouble(currentPrice + distance, _Digits);
    }
    else if(orderType == ORDER_TYPE_SELL_STOP)
    {
        return NormalizeDouble(currentPrice - distance, _Digits);
    }
    
    return 0;
}

// ============= 智能加仓配置参数 =============
input group "============= 智能加仓配置参数 ============="
input int SmartAddStartLevel = 5;           // 智能加仓起始单数
input int StrictAddStartLevel = 8;          // 严格加仓起始单数
input double TrendSlopeThreshold = 0.015;   // 趋势斜率阈值系数
input int TrendFilterScore = 70;            // 趋势过滤评分阈值
input double BBPositionThreshold = 0.3;     // 布林带位置阈值
input int RSI_Period_Smart = 14;            // RSI周期
input double RSI_Oversold_Smart = 35;       // RSI超卖阈值
input double RSI_Overbought_Smart = 65;     // RSI超买阈值

// ============= 智能手数算法参数 =============
input group "============= 智能手数算法参数 ============="
input int SmartLotMethod = 2;              // 手数计算方法(1=完整版, 2=简化版)
input double SmartLotDistanceAdjust = 0.15; // 距离调整系数(0.1-0.3)
input double SmartLotRiskAdjust = 0.04;     // 风险调整系数(0.02-0.06)
input double SmartLotVolatilityAdjust = 0.1; // 波动性调整系数(0.05-0.15)
input double SmartLotMaxMultiplier = 2.0;   // 最大手数倍率
input double SmartLotMinMultiplier = 1.1;   // 最小手数倍率
input int SmartLotRiskStart = 5;            // 风险控制起始订单数
input double SmartLotLowATR = 0.5;          // 低波动ATR阈值
input double SmartLotHighATR = 1.5;         // 高波动ATR阈值

// 智能加仓全局变量
struct SmartAddData {
    double currentPrice;
    double atr;
    double ma20[5];
    double bbUpper[3];
    double bbMiddle[3]; 
    double bbLower[3];
    double rsi[2];
    bool dataReady;
};

SmartAddData g_smartData;

// 智能加仓主判断
bool CanAddSmartOrder(bool isBuy, int orderCount, double lastAddPrice)
{
    string direction = isBuy ? "买入" : "卖出";
    datetime currentTime = TimeCurrent();
    bool shouldLog = (currentTime - g_lastSmartAddLog >= 60); // 每分钟记录一次日志
    
    // 前几单使用基本距离判断
    if(orderCount < SmartAddStartLevel - 1) {
        if(shouldLog) {
            PrintFormat("[%s智能加仓] 第%d单 - 基础加仓模式，直接允许", direction, orderCount+1);
            g_lastSmartAddLog = currentTime;
        }
        return true;
    }
    
    // 初始化指标数据
    if(!InitializeSmartAddData(isBuy)) {
        if(shouldLog) {
            PrintFormat("[%s智能加仓] 第%d单 - 数据获取失败，拒绝开仓", direction, orderCount+1);
            g_lastSmartAddLog = currentTime;
        }
        return false; // 数据获取失败，保守返回false
    }
    
    // 趋势强度判断
    bool trendStrong = IsTrendTooStrong(isBuy, orderCount, shouldLog);
    if(trendStrong) {
        if(shouldLog) {
            PrintFormat("[%s智能加仓] 第%d单 - 趋势过强，拒绝开仓", direction, orderCount+1);
            g_lastSmartAddLog = currentTime;
        }
        return false; // 趋势过强，不开仓
    }
    
    // 严格模式：需要明确的入场信号
    if(orderCount >= StrictAddStartLevel - 1) {
        bool hasSignal = HasValidEntrySignal(isBuy, lastAddPrice, shouldLog);
        if(shouldLog) {
            PrintFormat("[%s智能加仓] 第%d单 - 严格模式，入场信号:%s", direction, orderCount+1, hasSignal?"有":"无");
            g_lastSmartAddLog = currentTime;
        }
        return hasSignal;
    }
    
    // 普通模式：趋势不强即可
    if(shouldLog) {
        PrintFormat("[%s智能加仓] 第%d单 - 普通模式，趋势不强，允许开仓", direction, orderCount+1);
        g_lastSmartAddLog = currentTime;
    }
    return true;
}

// 初始化智能加仓数据
bool InitializeSmartAddData(bool isBuy)
{
    // 获取当前价格
    MqlTick latest_price;
    if(!SymbolInfoTick(_Symbol, latest_price)) return false;
    
    g_smartData.currentPrice = isBuy ? latest_price.bid : latest_price.ask;
    g_smartData.atr = g_atr;
    
    // 获取MA数据
    ArraySetAsSeries(g_smartData.ma20, true);
    if(CopyBuffer(g_ma20Handle, 0, 0, 5, g_smartData.ma20) <= 0) return false;
    
    // 获取布林带数据
    ArraySetAsSeries(g_smartData.bbUpper, true);
    ArraySetAsSeries(g_smartData.bbMiddle, true);
    ArraySetAsSeries(g_smartData.bbLower, true);
    
    if(CopyBuffer(g_bbHandle, 1, 0, 3, g_smartData.bbUpper) <= 0) return false;
    if(CopyBuffer(g_bbHandle, 0, 0, 3, g_smartData.bbMiddle) <= 0) return false;
    if(CopyBuffer(g_bbHandle, 2, 0, 3, g_smartData.bbLower) <= 0) return false;
    
    // 获取RSI数据
    int rsiHandle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period_Smart, PRICE_CLOSE);
    if(CopyBuffer(rsiHandle, 0, 0, 2, g_smartData.rsi) <= 0) return false;
    
    g_smartData.dataReady = true;
    return true;
}

// 判断趋势是否过强
bool IsTrendTooStrong(bool isBuy, int orderCount, bool shouldLog = false)
{
    if(!g_smartData.dataReady) return true; // 数据未准备好，保守判断
    
    // 计算趋势强度评分 (0-100)
    int trendScore = 0;
    
    // MA斜率判断
    double maSlope = (g_smartData.ma20[0] - g_smartData.ma20[4]) / 4;
    double maSlopeThreshold = g_smartData.atr * TrendSlopeThreshold;
    
    // 价格相对MA位置
    double priceToMA = (g_smartData.currentPrice - g_smartData.ma20[0]) / g_smartData.atr;
    
    // 布林带位置
    double bbPosition = 0;
    if(isBuy) {
        bbPosition = (g_smartData.currentPrice - g_smartData.bbLower[0]) / (g_smartData.bbUpper[0] - g_smartData.bbLower[0]);
    } else {
        bbPosition = (g_smartData.bbUpper[0] - g_smartData.currentPrice) / (g_smartData.bbUpper[0] - g_smartData.bbLower[0]);
    }
    
    if(isBuy) {
        // 买入时检查下跌趋势强度
        if(maSlope < -maSlopeThreshold) trendScore += 30;
        if(priceToMA < -1.0) trendScore += 25; // 价格远低于MA
        if(bbPosition > 0.8 ) trendScore += 25; // 价格异常位置：接近上轨或跌破下轨 || bbPosition < 0
        if(g_smartData.ma20[0] < g_smartData.ma20[1] && g_smartData.ma20[1] < g_smartData.ma20[2]) trendScore += 20; // 连续下跌
    } else {
        // 卖出时检查上涨趋势强度
        if(maSlope > maSlopeThreshold) trendScore += 30;
        if(priceToMA > 1.0) trendScore += 25; // 价格远高于MA
        if(bbPosition > 0.8 ) trendScore += 25; // 价格异常位置：接近下轨或突破上轨 || bbPosition < 0
        if(g_smartData.ma20[0] > g_smartData.ma20[1] && g_smartData.ma20[1] > g_smartData.ma20[2]) trendScore += 20; // 连续上涨
    }
    
    // 动态阈值（随订单数调整）
    int trendThreshold = TrendFilterScore;
    if(orderCount >= 6) trendThreshold = (int)(TrendFilterScore * 0.85); // 第6单开始放宽15%
    if(orderCount >= 8) trendThreshold = (int)(TrendFilterScore * 0.7);  // 第8单放宽30%
    if(orderCount >= 10) trendThreshold = (int)(TrendFilterScore * 0.4); // 第10单大幅放宽（安全阀）
    
    bool isTrendStrong = trendScore > trendThreshold;
    
    // 只在需要时打印趋势分析详情
    if(shouldLog) {
        string direction = isBuy ? "买入" : "卖出";
        PrintFormat("[%s趋势分析] 第%d单 | 趋势评分:%d | 阈值:%d | MA斜率:%.6f | 价格距MA:%.2f倍ATR | BB位置:%.2f | 结果:%s",
            direction, orderCount+1, trendScore, trendThreshold, maSlope, priceToMA, bbPosition, isTrendStrong?"趋势强":"趋势弱");
    }
    
    return isTrendStrong;
}

// 判断是否有有效的入场信号
bool HasValidEntrySignal(bool isBuy, double lastAddPrice, bool shouldLog = false)
{
    if(!g_smartData.dataReady) return false;
    
    string direction = isBuy ? "买入" : "卖出";
    bool hasSignal = false;
    string signalReasons = "";
    
    // 布林带位置信号
    double bbPosition = 0;
    bool bbSignal = false;
    if(isBuy) {
        bbPosition = (g_smartData.currentPrice - g_smartData.bbLower[0]) / (g_smartData.bbUpper[0] - g_smartData.bbLower[0]);
        // 检查是否接近下轨或从下轨反弹
        bool nearLowerBand = bbPosition < BBPositionThreshold;
        bool bounceFromLower = g_smartData.currentPrice > g_smartData.bbLower[1] && g_smartData.bbLower[1] <= g_smartData.bbLower[2];
        bbSignal = nearLowerBand || bounceFromLower;
        if(bbSignal) {
            hasSignal = true;
            if(nearLowerBand) signalReasons += "接近下轨 ";
            if(bounceFromLower) signalReasons += "下轨反弹 ";
        }
    } else {
        bbPosition = (g_smartData.bbUpper[0] - g_smartData.currentPrice) / (g_smartData.bbUpper[0] - g_smartData.bbLower[0]);
        // 检查是否接近上轨或从上轨回落
        bool nearUpperBand = bbPosition < BBPositionThreshold;
        bool fallFromUpper = g_smartData.currentPrice < g_smartData.bbUpper[1] && g_smartData.bbUpper[1] >= g_smartData.bbUpper[2];
        bbSignal = nearUpperBand || fallFromUpper;
        if(bbSignal) {
            hasSignal = true;
            if(nearUpperBand) signalReasons += "接近上轨 ";
            if(fallFromUpper) signalReasons += "上轨回落 ";
        }
    }
    
    // RSI回调信号
    bool rsiSignal = false;
    if(isBuy && g_smartData.rsi[0] < RSI_Oversold_Smart && g_smartData.rsi[0] > g_smartData.rsi[1]) {
        rsiSignal = true;
        hasSignal = true;
        signalReasons += "RSI超卖回升 ";
    }
    if(!isBuy && g_smartData.rsi[0] > RSI_Overbought_Smart && g_smartData.rsi[0] < g_smartData.rsi[1]) {
        rsiSignal = true;
        hasSignal = true;
        signalReasons += "RSI超买回落 ";
    }
    
    // 价格继续不利方向移动（兜底信号）
    bool priceSignal = false;
    if(isBuy && g_smartData.currentPrice < lastAddPrice * 0.999) {
        priceSignal = true;
        hasSignal = true;
        signalReasons += "价格继续下跌 ";
    }
    if(!isBuy && g_smartData.currentPrice > lastAddPrice * 1.001) {
        priceSignal = true;
        hasSignal = true;
        signalReasons += "价格继续上涨 ";
    }
    
    // 只在需要时打印入场信号分析
    if(shouldLog) {
        PrintFormat("[%s入场信号] BB位置:%.2f | RSI:%.1f | 布林带信号:%s | RSI信号:%s | 价格信号:%s | 原因:%s",
            direction, bbPosition, g_smartData.rsi[0], bbSignal?"有":"无", rsiSignal?"有":"无", priceSignal?"有":"无", 
            signalReasons != "" ? signalReasons : "无信号");
    }
    
    return hasSignal;
}

// ============= 智能手数计算函数 =============



// 直接计算智能手数（推荐使用）
double CalculateSmartLotSize(bool isBuy, double lastPrice, double currentPrice, double atr, double lastLot)
{
    // 基础参数
    const double baseMultiplier = g_MultiplierOnLoss;  // 基础倍率M
    const double baseDistance = g_AtrRange;            // 基础距离倍率N
    
    // 计算实际价格距离（以ATR为单位）
    double priceDistance = MathAbs(currentPrice - lastPrice);
    double distanceInAtr = priceDistance / atr;
    
    // 获取当前订单数量
    int orderCount = isBuy ? buyOrderCount : sellOrderCount;
    
    // 核心算法：基于距离和风险的手数计算
    double lotMultiplier = baseMultiplier;
    
    if(distanceInAtr > baseDistance) {
        // 智能加仓情况：距离超过基准距离
        double distanceRatio = distanceInAtr / baseDistance;
        
        // 使用对数函数调整，避免手数增长过快
        lotMultiplier = baseMultiplier * (1.0 + SmartLotDistanceAdjust * MathLog(distanceRatio));
    } else {
        // 正常加仓情况：距离小于等于基准距离
        // 使用标准倍率，但稍微保守
        lotMultiplier = baseMultiplier * 0.95;
    }
    
    // 根据订单数量进行风险控制
    if(orderCount > SmartLotRiskStart) {
        // 订单数量较多时，降低手数倍率
        double riskAdjust = 1.0 - SmartLotRiskAdjust * (orderCount - SmartLotRiskStart);
        lotMultiplier *= MathMax(0.6, riskAdjust);
    }
    
    // 根据ATR波动性调整
    if(atr < SmartLotLowATR) {
        // 低波动时，降低手数
        lotMultiplier *= (1.0 - SmartLotVolatilityAdjust);
    } else if(atr > SmartLotHighATR) {
        // 高波动时，适当提高手数
        lotMultiplier *= (1.0 + SmartLotVolatilityAdjust);
    }
    
    // 确保手数倍率在合理范围内
    lotMultiplier = MathMin(SmartLotMaxMultiplier, MathMax(SmartLotMinMultiplier, lotMultiplier));
    
    // 计算最终手数
    double finalLot = NormalizeDouble(lastLot * lotMultiplier, 2);
    
    // 确保手数不小于最小手数
    double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
    if(finalLot < minLot) {
        finalLot = minLot;
    }
    
    // 打印智能手数计算详情
    string direction = isBuy ? "买入" : "卖出";
    PrintFormat("[%s智能手数] 基础手数:%.2f | 价格距离:%.5f | ATR距离:%.2f | 手数倍率:%.3f | 最终手数:%.2f",
        direction, lastLot, priceDistance, distanceInAtr, lotMultiplier, finalLot);
    
    return finalLot;
}

// 简化版智能手数计算（基于您提到的数学公式）
double CalculateSimpleSmartLot(bool isBuy, double lastPrice, double currentPrice, double atr, double lastLot)
{
    // 基础参数
    const double baseMultiplier = g_MultiplierOnLoss;  // 基础倍率M
    const double baseDistance = g_AtrRange;            // 基础距离倍率N
    
    // 计算实际价格距离（以ATR为单位）
    double priceDistance = MathAbs(currentPrice - lastPrice);
    double distanceInAtr = priceDistance / atr;
    
    // 获取当前订单数量
    int orderCount = isBuy ? buyOrderCount : sellOrderCount;
    
    // 核心公式：基于距离比例调整倍率
    double lotMultiplier = baseMultiplier;
    
    if(distanceInAtr > baseDistance) {
        // 智能加仓：距离超过基准距离
        double distanceRatio = distanceInAtr / baseDistance;
        
        // 使用线性调整，更简单直接
        lotMultiplier = baseMultiplier * (1.0 + 0.2 * (distanceRatio - 1.0));
    } else {
        // 正常加仓：使用标准倍率
        lotMultiplier = baseMultiplier;
    }
    
    // 简单的风险控制：订单数量超过8单时降低倍率
    if(orderCount > 8) {
        lotMultiplier *= 0.9;
    }
    
    // 确保倍率在合理范围内
    lotMultiplier = MathMin(2.5, MathMax(1.1, lotMultiplier));
    
    // 计算最终手数
    double finalLot = NormalizeDouble(lastLot * lotMultiplier, 2);
    
    // 打印简化智能手数计算详情
    string direction = isBuy ? "买入" : "卖出";
    PrintFormat("[%s简化手数] 基础手数:%.2f | 价格距离:%.5f | ATR距离:%.2f | 手数倍率:%.3f | 最终手数:%.2f",
        direction, lastLot, priceDistance, distanceInAtr, lotMultiplier, finalLot);
    
    return finalLot;
}
